home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #11 / Amiga Plus CD - 2004 - No. 11.iso / AmiSoft / Game / misc / WormWars.lha / WormWars / Source / engine2.c < prev    next >
C/C++ Source or Header  |  2004-08-22  |  108KB  |  2,876 lines

  1. // 1. INCLUDES -----------------------------------------------------------
  2.  
  3. #include "stdafx.h"
  4. #include "diff.h"
  5. #include "same.h"
  6. #include "engine.h"
  7.  
  8. #define ASSERT
  9. #include <assert.h>
  10. #include <stdlib.h>                    // abs()
  11.  
  12. // 2. DEFINES ------------------------------------------------------------
  13.  
  14. // 3. EXPORTED VARIABLES -------------------------------------------------
  15.  
  16. AGLOBAL UBYTE birdframes[BIRDFRAMES + 1] =
  17. { BIRD,
  18.   FIRSTBIRDFRAME,
  19.   FIRSTBIRDFRAME + 1,
  20.   FIRSTBIRDFRAME + 2,
  21.   FIRSTBIRDFRAME + 3
  22. },
  23. missileframes[4][MISSILEFRAMES + 1] =
  24. { { FIRSTMISSILE,          // green (p1)
  25.     FIRSTMISSILEFRAME,
  26.     FIRSTMISSILEFRAME + 1,
  27.     FIRSTMISSILEFRAME + 2,
  28.     FIRSTMISSILEFRAME + 3,
  29.     FIRSTMISSILEFRAME + 4
  30.   },
  31.   { FIRSTMISSILE + 1,      // red (p2)
  32.     FIRSTMISSILEFRAME + 5,
  33.     FIRSTMISSILEFRAME + 6,
  34.     FIRSTMISSILEFRAME + 7,
  35.     FIRSTMISSILEFRAME + 8,
  36.     FIRSTMISSILEFRAME + 9
  37.   },
  38.   { FIRSTMISSILE + 2,      // blue (p3)
  39.     FIRSTMISSILEFRAME + 10,
  40.     FIRSTMISSILEFRAME + 11,
  41.     FIRSTMISSILEFRAME + 12,
  42.     FIRSTMISSILEFRAME + 13,
  43.     FIRSTMISSILEFRAME + 14,
  44.   },
  45.   { FIRSTMISSILE + 3,      // yellow (p4)
  46.     FIRSTMISSILEFRAME + 15,
  47.     FIRSTMISSILEFRAME + 16,
  48.     FIRSTMISSILEFRAME + 17,
  49.     FIRSTMISSILEFRAME + 18,
  50.     FIRSTMISSILEFRAME + 19
  51. } },
  52. bananaframes[4][BANANAFRAMES + 1] =
  53. { { FIRSTBANANA,
  54.     FIRSTBANANAFRAME +  0,
  55.     FIRSTBANANAFRAME +  1,
  56.     FIRSTBANANAFRAME +  2,
  57.     FIRSTBANANAFRAME +  3,
  58.     FIRSTBANANAFRAME +  4,
  59.     FIRSTBANANAFRAME +  5,
  60.     FIRSTBANANAFRAME +  6,
  61.   },
  62.   { FIRSTBANANA + 1,
  63.     FIRSTBANANAFRAME +  7,
  64.     FIRSTBANANAFRAME +  8,
  65.     FIRSTBANANAFRAME +  9,
  66.     FIRSTBANANAFRAME + 10,
  67.     FIRSTBANANAFRAME + 11,
  68.     FIRSTBANANAFRAME + 12,
  69.     FIRSTBANANAFRAME + 13,
  70.   },
  71.   { FIRSTBANANA + 2,
  72.     FIRSTBANANAFRAME + 14,
  73.     FIRSTBANANAFRAME + 15,
  74.     FIRSTBANANAFRAME + 16,
  75.     FIRSTBANANAFRAME + 17,
  76.     FIRSTBANANAFRAME + 18,
  77.     FIRSTBANANAFRAME + 19,
  78.     FIRSTBANANAFRAME + 20,
  79.   },
  80.   { FIRSTBANANA + 3,
  81.     FIRSTBANANAFRAME + 21,
  82.     FIRSTBANANAFRAME + 22,
  83.     FIRSTBANANAFRAME + 23,
  84.     FIRSTBANANAFRAME + 24,
  85.     FIRSTBANANAFRAME + 25,
  86.     FIRSTBANANAFRAME + 26,
  87.     FIRSTBANANAFRAME + 27,
  88. } };
  89.  
  90. // 4. IMPORTED VARIABLES -------------------------------------------------
  91.  
  92. // from engine1.c
  93. IMPORT ABOOL                     banging,
  94.                                  enclosed;
  95. IMPORT UBYTE                     field[MAXFIELDX + 1][MAXFIELDY + 1],
  96.                                  tailfield[MAXFIELDX + 1][MAXFIELDY + 1];
  97. IMPORT SBYTE                     level,
  98.                                  numberx,
  99.                                  numbery,
  100.                                  number,
  101.                                  treasurer,
  102.                                  players,
  103.                                  levels,
  104.                                  reallevel;
  105. IMPORT SWORD                     fieldx, fieldy,
  106.                                  secondsleft,
  107.                                  secondsperlevel;
  108. IMPORT ULONG                     r;
  109. IMPORT struct CreatureStruct     creature[CREATURES + 1];
  110. IMPORT struct MagnetStruct       magnet[MAGNETS + 1];
  111. IMPORT struct ObjectStruct       object[LASTOBJECT + 1];
  112. IMPORT struct ProtectorStruct    protector[4][PROTECTORS + 1];
  113. IMPORT struct TeleportStruct     teleport[2];
  114. IMPORT struct WormStruct         worm[4];
  115. IMPORT struct CreatureInfoStruct creatureinfo[SPECIES + 1];
  116.  
  117. // 5. MODULE VARIABLES ---------------------------------------------------
  118.  
  119. // 6. MODULE STRUCTURES --------------------------------------------------
  120.  
  121. MODULE struct
  122. {   SBYTE deltax, deltay;
  123. } thedogqueue[CREATURES + 1][DOGQUEUELIMIT + 1];
  124. MODULE struct
  125. {   SBYTE deltax, deltay;
  126. } thewormqueue[4][WORMQUEUELIMIT + 1];
  127. struct
  128. {   SBYTE x, y, deltax, deltay;
  129.     ABOOL alive, moved, teleported, visible, reflected;
  130. } bullet[9];
  131. MODULE UBYTE eachtail[4][2][9][9] = {
  132. { { { GN_SE_NW,      GN_SE_N,       GN_SE_NE, // going NW (delta -1, -1)
  133.       GN_SE_W,       WHATEVER,      GN_SE_E,  // (so starting from SE)
  134.       GN_SE_SW,      GN_SE_S,       GN_SE_NW
  135.     },
  136.     { GN_S_NW,       GN_S_N,        GN_S_NE,  // going N (delta 0, -1)
  137.       GN_S_W,        WHATEVER,      GN_S_E,   // (so starting from S)
  138.       GN_S_SW,       GN_S_N,        GN_S_SE
  139.     },
  140.     { GN_SW_NW,      GN_SW_N,       GN_SW_NE, // going NE (delta 0, 1)
  141.       GN_SW_W,       WHATEVER,      GN_SW_E,  // (so starting from SW)
  142.       GN_SW_NE,      GN_SW_S,       GN_SW_SE
  143.     },
  144.     { GN_E_NW,       GN_E_N,        GN_E_NE,  // going W (delta -1, 0)
  145.       GN_E_W,        WHATEVER,      GN_E_W,   // (so starting from E)
  146.       GN_E_SW,       GN_E_S,        GN_E_SE
  147.     },
  148.     { GN_SE_NW,      GN_S_N,        GN_SW_NE, // going nowhere (delta 0, 0)
  149.       GN_E_W,        WHATEVER,      GN_W_E,
  150.       GN_NE_SW,      GN_N_S,        GN_NW_SE
  151.     },
  152.     { GN_W_NW,       GN_W_N,        GN_W_NE,  // going E (delta 1, 0)
  153.       GN_W_E,        WHATEVER,      GN_W_E,   // (so starting from W)
  154.       GN_W_SW,       GN_W_S,        GN_W_SE
  155.     },
  156.     { GN_NE_NW,      GN_NE_N,       GN_NE_NW, // going SW (delta -1, 1)
  157.       GN_NE_W,       WHATEVER,      GN_NE_E,  // (so starting from NE)
  158.       GN_NE_SW,      GN_NE_S,       GN_NE_SE
  159.     },
  160.     { GN_N_NW,       GN_N_S,        GN_N_NE,  // going S (delta 0, 1)
  161.       GN_N_W,        WHATEVER,      GN_N_E,   // (so starting from N)
  162.       GN_N_SW,       GN_N_S,        GN_N_SE
  163.     },
  164.     { GN_NW_SE,      GN_NW_N,       GN_NW_NE, // going SE (delta 1, 1)
  165.       GN_NW_W,       WHATEVER,      GN_NW_E,  // (so starting from NW)
  166.       GN_NW_SW,      GN_NW_S,       GN_NW_SE
  167.   } },
  168.   { { GG_SE_NW,      GG_SE_N,       GG_SE_NE, // going NW (delta -1, -1)
  169.       GG_SE_W,       WHATEVER,      GG_SE_E,  // (so starting from SE)
  170.       GG_SE_SW,      GG_SE_S,       GG_SE_NW
  171.     },
  172.     { GG_S_NW,       GG_S_N,        GG_S_NE,  // going N (delta 0, -1)
  173.       GG_S_W,        WHATEVER,      GG_S_E,   // (so starting from S)
  174.       GG_S_SW,       GG_S_N,        GG_S_SE
  175.     },
  176.     { GG_SW_NW,      GG_SW_N,       GG_SW_NE, // going NE (delta 0, 1)
  177.       GG_SW_W,       WHATEVER,      GG_SW_E,  // (so starting from SW)
  178.       GG_SW_NE,      GG_SW_S,       GG_SW_SE
  179.     },
  180.     { GG_E_NW,       GG_E_N,        GG_E_NE,  // going W (delta -1, 0)
  181.       GG_E_W,        WHATEVER,      GG_E_W,   // (so starting from E)
  182.       GG_E_SW,       GG_E_S,        GG_E_SE
  183.     },
  184.     { GG_SE_NW,      GG_S_N,        GG_SW_NE, // going nowhere (delta 0, 0)
  185.       GG_E_W,        WHATEVER,      GG_W_E,
  186.       GG_NE_SW,      GG_N_S,        GG_NW_SE
  187.     },
  188.     { GG_W_NW,       GG_W_N,        GG_W_NE,  // going E (delta 1, 0)
  189.       GG_W_E,        WHATEVER,      GG_W_E,   // (so starting from W)
  190.       GG_W_SW,       GG_W_S,        GG_W_SE
  191.     },
  192.     { GG_NE_NW,      GG_NE_N,       GG_NE_SW, // going SW (delta -1, 1)
  193.       GG_NE_W,       WHATEVER,      GG_NE_E,  // (so starting from NE)
  194.       GG_NE_SW,      GG_NE_S,       GG_NE_SE
  195.     },
  196.     { GG_N_NW,       GG_N_S,        GG_N_NE,  // going S (delta 0, 1)
  197.       GG_N_W,        WHATEVER,      GG_N_E,   // (so starting from N)
  198.       GG_N_SW,       GG_N_S,        GG_N_SE
  199.     },
  200.     { GG_NW_SE,      GG_NW_N,       GG_NW_NE, // going SE (delta 1, 1)
  201.       GG_NW_W,       WHATEVER,      GG_NW_E,  // (so starting from NW)
  202.       GG_NW_SW,      GG_NW_S,       GG_NW_SE
  203. } } },
  204. { { { RN_SE_NW,      RN_SE_N,       RN_SE_NE, // going NW (delta -1, -1)
  205.       RN_SE_W,       WHATEVER,      RN_SE_E,  // (so starting from SE)
  206.       RN_SE_SW,      RN_SE_S,       RN_SE_NW,
  207.     },
  208.     { RN_S_NW,       RN_S_N,        RN_S_NE,  // going N (delta 0, -1)
  209.       RN_S_W,        WHATEVER,      RN_S_E,   // (so starting from S)
  210.       RN_S_SW,       RN_S_N,        RN_S_SE
  211.     },
  212.     { RN_SW_NW,      RN_SW_N,       RN_SW_NE, // going NE (delta 0, 1)
  213.       RN_SW_W,       WHATEVER,      RN_SW_E,  // (so starting from SW)
  214.       RN_SW_NE,      RN_SW_S,       RN_SW_SE
  215.     },
  216.     { RN_E_NW,       RN_E_N,        RN_E_NE,  // going W (delta -1, 0)
  217.       RN_E_W,        WHATEVER,      RN_E_W,   // (so starting from E)
  218.       RN_E_SW,       RN_E_S,        RN_E_SE
  219.     },
  220.     { RN_SE_NW,      RN_S_N,        RN_SW_NE, // going nowhere (delta 0, 0)
  221.       RN_E_W,        WHATEVER,      RN_W_E,
  222.       RN_NE_SW,      RN_N_S,        RN_NW_SE
  223.     },
  224.     { RN_W_NW,       RN_W_N,        RN_W_NE,  // going E (delta 1, 0)
  225.       RN_W_E,        WHATEVER,      RN_W_E,   // (so starting from W)
  226.       RN_W_SW,       RN_W_S,        RN_W_SE
  227.     },
  228.     { RN_NE_NW,      RN_NE_N,       RN_NE_SW, // going SW (delta -1, 1)
  229.       RN_NE_W,       WHATEVER,      RN_NE_E,  // (so starting from NE)
  230.       RN_NE_SW,      RN_NE_S,       RN_NE_SE
  231.     },
  232.     { RN_N_NW,       RN_N_S,        RN_N_NE,  // going S (delta 0, 1)
  233.       RN_N_W,        WHATEVER,      RN_N_E,   // (so starting from N)
  234.       RN_N_SW,       RN_N_S,        RN_N_SE
  235.     },
  236.     { RN_NW_SE,      RN_NW_N,       RN_NW_NE, // going SE (delta 1, 1)
  237.       RN_NW_W,       WHATEVER,      RN_NW_E,  // (so starting from NW)
  238.       RN_NW_SW,      RN_NW_S,       RN_NW_SE
  239.   } },
  240.   { { RG_SE_NW,      RG_SE_N,       RG_SE_NE, // going NW (delta -1, -1)
  241.       RG_SE_W,       WHATEVER,      RG_SE_E,  // (so starting from SE)
  242.       RG_SE_SW,      RG_SE_S,       RG_SE_NW
  243.     },
  244.     { RG_S_NW,       RG_S_N,        RG_S_NE,  // going N (delta 0, -1)
  245.       RG_S_W,        WHATEVER,      RG_S_E,   // (so starting from S)
  246.       RG_S_SW,       RG_S_N,        RG_S_SE
  247.     },
  248.     { RG_SW_NW,      RG_SW_N,       RG_SW_NE, // going NE (delta 0, 1)
  249.       RG_SW_W,       WHATEVER,      RG_SW_E,  // (so starting from SW)
  250.       RG_SW_NE,      RG_SW_S,       RG_SW_SE
  251.     },
  252.     { RG_E_NW,       RG_E_N,        RG_E_NE,  // going W (delta -1, 0)
  253.       RG_E_W,        WHATEVER,      RG_E_W,   // (so starting from E)
  254.       RG_E_SW,       RG_E_S,        RG_E_SE
  255.     },
  256.     { RG_SE_NW,      RG_S_N,        RG_SW_NE, // going nowhere (delta 0, 0)
  257.       RG_E_W,        WHATEVER,      RG_W_E,
  258.       RG_NE_SW,      RG_N_S,        RG_NW_SE
  259.     },
  260.     { RG_W_NW,       RG_W_N,        RG_W_NE,  // going E (delta 1, 0)
  261.       RG_W_E,        WHATEVER,      RG_W_E,   // (so starting from W)
  262.       RG_W_SW,       RG_W_S,        RG_W_SE
  263.     },
  264.     { RG_NE_NW,      RG_NE_N,       RG_NE_SW, // going SW (delta -1, 1)
  265.       RG_NE_W,       WHATEVER,      RG_NE_E,  // (so starting from NE)
  266.       RG_NE_SW,      RG_NE_S,       RG_NE_SE
  267.     },
  268.     { RG_N_NW,       RG_N_S,        RG_N_NE,  // going S (delta 0, 1)
  269.       RG_N_W,        WHATEVER,      RG_N_E,   // (so starting from N)
  270.       RG_N_SW,       RG_N_S,        RG_N_SE
  271.     },
  272.     { RG_NW_SE,      RG_NW_N,       RG_NW_NE, // going SE (delta 1, 1)
  273.       RG_NW_W,       WHATEVER,      RG_NW_E,  // (so starting from NW)
  274.       RG_NW_SW,      RG_NW_S,       RG_NW_SE
  275. } } },
  276. { { { BN_NW_SE,      BN_N_SE,       BN_NE_SE, // going NW (delta -1, -1)
  277.       BN_W_SE,       WHATEVER,      BN_E_SE,  // (so starting from SE)
  278.       BN_SW_SE,      BN_S_SE,       BN_NW_SE
  279.     },
  280.     { BN_NW_S,       BN_N_S,        BN_NE_S,  // going N (delta 0, -1)
  281.       BN_W_S,        WHATEVER,      BN_E_S,   // (so starting from S)
  282.       BN_S_SW,       BN_N_S,        BN_S_SE
  283.     },
  284.     { BN_NW_SW,      BN_N_SW,       BN_NE_SW, // going NE (delta 0, 1)
  285.       BN_W_SW,       WHATEVER,      BN_SW_E,  // (so starting from SW)
  286.       BN_NE_SW,      BN_S_SW,       BN_SW_SE
  287.     },
  288.     { BN_NW_E,       BN_N_E,        BN_E_NE,  // going W (delta -1, 0)
  289.       BN_W_E,        WHATEVER,      BN_W_E,   // (so starting from E)
  290.       BN_SW_E,       BN_E_S,        BN_E_SE
  291.     },
  292.     { BN_NW_SE,      BN_N_S,        BN_NE_SW, // going nowhere (delta 0, 0)
  293.       BN_W_E,        WHATEVER,      BN_W_E,
  294.       BN_NE_SW,      BN_N_S,        BN_NW_SE
  295.     },
  296.     { BN_W_NW,       BN_N_W,        BN_W_NE,  // going E (delta 1, 0)
  297.       BN_W_E,        WHATEVER,      BN_W_E,   // (so starting from W)
  298.       BN_W_SW,       BN_W_S,        BN_W_SE
  299.     },
  300.     { BN_NW_NE,      BN_N_NE,       BN_NE_SW, // going SW (delta -1, 1)
  301.       BN_W_NE,       WHATEVER,      BN_E_NE,  // (so starting from NE)
  302.       BN_NE_SW,      BN_NE_S,       BN_NE_SE
  303.     },
  304.     { BN_N_NW,       BN_N_S,        BN_N_NE,  // going S (delta 0, 1)
  305.       BN_N_W,        WHATEVER,      BN_N_E,   // (so starting from N)
  306.       BN_N_SW,       BN_N_S,        BN_N_SE
  307.     },
  308.     { BN_SW_SE,      BN_N_NW,       BN_NW_NE, // going SE (delta 1, 1)
  309.       BN_W_NW,       WHATEVER,      BN_NW_E,  // (so starting from NW)
  310.       BN_NW_SW,      BN_NW_S,       BN_NW_SE
  311.   } },
  312.   { { BG_NW_SE,      BG_N_SE,       BG_NE_SE, // going NW (delta -1, -1)
  313.       BG_W_SE,       WHATEVER,      BG_E_SE,  // (so starting from SE)
  314.       BG_SW_SE,      BG_S_SE,       BG_NW_SE
  315.     },
  316.     { BG_NW_S,       BG_N_S,        BG_NE_S,  // going N (delta 0, -1)
  317.       BG_W_S,        WHATEVER,      BG_E_S,   // (so starting from S)
  318.       BG_S_SW,       BG_N_S,        BG_S_SE
  319.     },
  320.     { BG_NW_SW,      BG_N_SW,       BG_NE_SW, // going NE (delta 0, 1)
  321.       BG_W_SW,       WHATEVER,      BG_SW_E,  // (so starting from SW)
  322.       BG_NE_SW,      BG_S_SW,       BG_SW_SE
  323.     },
  324.     { BG_NE_E,       BG_N_E,        BG_NE_E,  // going W (delta -1, 0)
  325.       BG_W_E,        WHATEVER,      BG_W_E,   // (so starting from E)
  326.       BG_SW_E,       BG_E_S,        BG_E_SE
  327.     },
  328.     { BG_NW_SE,      BG_N_S,        BG_NE_SW, // going nowhere (delta 0, 0)
  329.       BG_W_E,        WHATEVER,      BG_W_E,
  330.       BG_NE_SW,      BG_N_S,        BG_NW_SE
  331.     },
  332.     { BG_NW_W,       BG_N_W,        BG_NE_W,  // going E (delta 1, 0)
  333.       BG_W_E,        WHATEVER,      BG_W_E,   // (so starting from W)
  334.       BG_W_SW,       BG_W_S,        BG_W_SE
  335.     },
  336.     { BG_NW_NE,      BG_N_NE,       BG_NE_SW, // going SW (delta -1, 1)
  337.       BG_NE_W,       WHATEVER,      BG_NE_E,  // (so starting from NE)
  338.       BG_NE_SW,      BG_NE_S,       BG_NE_SE
  339.     },
  340.     { BG_N_NW,       BG_N_S,        BG_N_NE,  // going S (delta 0, 1)
  341.       BG_N_W,        WHATEVER,      BG_N_E,   // (so starting from N)
  342.       BG_N_SW,       BG_N_S,        BG_N_SE
  343.     },
  344.     { BG_NW_SE,      BG_N_NW,       BG_NW_NE, // going SE (delta 1, 1)
  345.       BG_NW_W,       WHATEVER,      BG_NW_E,  // (so starting from NW)
  346.       BG_NW_SW,      BG_NW_S,       BG_NW_SE
  347. } } },
  348. { { { YN_NW_SE,      YN_N_SE,       YN_NE_SE, // going NW (delta -1, -1)
  349.       YN_W_SE,       WHATEVER,      YN_E_SE,  // (so starting from SE)
  350.       YN_SW_SE,      YN_S_SE,       YN_NW_SE
  351.     },
  352.     { YN_NW_S,       YN_N_S,        YN_NE_S,  // going N (delta 0, -1)
  353.       YN_W_S,        WHATEVER,      YN_S_E,   // (so starting from S)
  354.       YN_S_SW,       YN_N_S,        YN_S_SE
  355.     },
  356.     { YN_NW_SW,      YN_N_SW,       YN_NE_SW, // going NE (delta 0, 1)
  357.       YN_W_SW,       WHATEVER,      YN_E_SW,  // (so starting from SW)
  358.       YN_NE_SW,      YN_S_SW,       YN_SW_SE
  359.     },
  360.     { YN_NW_E,       YN_N_E,        YN_NE_E,  // going W (delta -1, 0)
  361.       YN_W_E,        WHATEVER,      YN_W_E,   // (so starting from E)
  362.       YN_E_SW,       YN_S_E,        YN_E_SE
  363.     },
  364.     { YN_NW_SE,      YN_N_S,        YN_NE_SW, // going nowhere (delta 0, 0)
  365.       YN_W_E,        WHATEVER,      YN_W_E,
  366.       YN_NE_SW,      YN_N_S,        YN_NW_SE
  367.     },
  368.     { YN_NW_W,       YN_N_W,        YN_W_NE,  // going E (delta 1, 0)
  369.       YN_W_E,        WHATEVER,      YN_W_E,   // (so starting from W)
  370.       YN_W_SW,       YN_W_S,        YN_W_SE
  371.     },
  372.     { YN_NW_NE,      YN_N_NE,       YN_NE_SW, // going SW (delta -1, 1)
  373.       YN_W_NE,       WHATEVER,      YN_NE_E,  // (so starting from NE)
  374.       YN_NE_SW,      YN_NE_S,       YN_NE_SE
  375.     },
  376.     { YN_N_NW,       YN_N_S,        YN_N_NE,  // going S (delta 0, 1)
  377.       YN_N_W,        WHATEVER,      YN_N_E,   // (so starting from N)
  378.       YN_N_SW,       YN_N_S,        YN_N_SE
  379.     },
  380.     { YN_NW_SE,      YN_N_NW,       YN_NW_NE, // going SE (delta 1, 1)
  381.       YN_NW_W,       WHATEVER,      YN_NW_E,  // (so starting from NW)
  382.       YN_NW_SW,      YN_NW_S,       YN_NW_SE
  383.   } },
  384.   { { YG_NW_SE,      YG_N_SE,       YG_NE_SE, // going NW (delta -1, -1)
  385.       YG_W_SE,       WHATEVER,      YG_E_SE,  // (so starting from SE)
  386.       YG_SW_SE,      YG_S_SE,       YG_NW_SE
  387.     },
  388.     { YG_S_NW,       YG_N_S,        YG_S_NE,  // going N (delta 0, -1)
  389.       YG_W_S,        WHATEVER,      YG_E_S,   // (so starting from S)
  390.       YG_S_SW,       YG_N_S,        YG_S_SE
  391.     },
  392.     { YG_NW_SW,      YG_N_SW,       YG_NE_SW, // going NE (delta 0, 1)
  393.       YG_W_SW,       WHATEVER,      YG_E_SW,  // (so starting from SW)
  394.       YG_NE_SW,      YG_S_SW,       YG_SW_SE
  395.     },
  396.     { YG_E_NW,       YG_E_N,        YG_E_NE,  // going W (delta -1, 0)
  397.       YG_W_E,        WHATEVER,      YG_W_E,   // (so starting from E)
  398.       YG_E_SW,       YG_E_S,        YG_E_SE
  399.     },
  400.     { YG_NW_SE,      YG_N_S,        YG_NE_SW, // going nowhere (delta 0, 0)
  401.       YG_W_E,        WHATEVER,      YG_W_E,
  402.       YG_NE_SW,      YG_N_S,        YG_NW_SE
  403.     },
  404.     { YG_W_NW,       YG_N_W,        YG_W_NE,  // going E (delta 1, 0)
  405.       YG_W_E,        WHATEVER,      YG_W_E,   // (so starting from W)
  406.       YG_W_SW,       YG_W_S,        YG_W_SE
  407.     },
  408.     { YG_NW_NE,      YG_N_NE,       YG_NE_SW, // going SW (delta -1, 1)
  409.       YG_W_NE,       WHATEVER,      YG_E_NE,  // (so starting from NE)
  410.       YG_NE_SW,      YG_S_NE,       YG_NE_SE
  411.     },
  412.     { YG_N_NW,       YG_N_S,        YG_N_NE,  // going S (delta 0, 1)
  413.       YG_N_W,        WHATEVER,      YG_E_N,   // (so starting from N)
  414.       YG_N_SW,       YG_N_S,        YG_N_SE
  415.     },
  416.     { YG_NW_SE,      YG_N_NW,       YG_NW_NE, // going SE (delta 1, 1)
  417.       YG_W_NW,       WHATEVER,      YG_E_NW,  // (so starting from NW)
  418.       YG_NW_SW,      YG_S_NW,       YG_NW_SE
  419. } } }
  420. };
  421.  
  422. // 7. MODULE FUNCTIONS ---------------------------------------------------
  423.  
  424. MODULE void creaturebullet(SBYTE x, SBYTE y, SBYTE deltax, SBYTE deltay, UBYTE subspecies);
  425. MODULE void creaturecreature(UBYTE which1, UBYTE which2);
  426. MODULE ABOOL bouncecreature(UBYTE which, SBYTE x, SBYTE y);
  427. MODULE void bounceoffcreature(UBYTE which, SBYTE x, SBYTE y);
  428. MODULE void dogqueue(SBYTE which, SBYTE deltax, SBYTE deltay);
  429. MODULE void protcol(SBYTE player, SBYTE x, SBYTE y, SBYTE thisprot);
  430. MODULE void wormbullet(SBYTE player);
  431. MODULE void choosediagonal(UBYTE which);
  432. MODULE void chooseorthagonal(SBYTE* xx, SBYTE* yy);
  433. MODULE void protectorloop1(SBYTE player);
  434. MODULE void protectorloop2(SBYTE player);
  435. MODULE void turncreature(UBYTE which);
  436.  
  437. // 8. CODE ---------------------------------------------------------------
  438.  
  439. AGLOBAL void createcreature(UBYTE species,
  440.                             UBYTE which,
  441.                             SBYTE x,
  442.                             SBYTE y,
  443.                             SBYTE deltax,
  444.                             SBYTE deltay,
  445.                             UBYTE player,
  446.                             UBYTE subspecies
  447.                            )
  448. {   if (species != ORB)
  449.     {   creature[which].deltax  = deltax;
  450.         creature[which].deltay  = deltay;
  451.     }
  452.  
  453.     if (species != CAMEL)
  454.     {   creature[which].subspecies = subspecies;
  455.     }
  456.  
  457.     if (species == MISSILE_C)
  458.     {    creature[which].visible = FALSE;
  459.     } else creature[which].visible = TRUE;
  460.  
  461. /*  This is something of a workaround to get around the problem where the
  462.     tail/glow that eg. a fish appears on is not restored to the correct
  463.     glow-image...
  464.     if (creatureinfo[species - FIRSTCREATURE].wall == TRUE)
  465.     {   creature[which].last = creature[which].oldlast = field[x][y];
  466.     } else */
  467.     creature[which].last = creature[which].oldlast = EMPTY;
  468.  
  469.     creature[which].alive   = TRUE;
  470.     creature[which].x       = x;
  471.     creature[which].y       = y;
  472.     creature[which].species = species;
  473.     creature[which].player  = player;
  474.     creature[which].speed   = creatureinfo[species - FIRSTCREATURE].speed;
  475.     creature[which].score   = creatureinfo[species - FIRSTCREATURE].score;
  476.  
  477.     switch(species)
  478.     {
  479.     case HORSE:
  480.         creature[which].dir      = arand(7);
  481.         turncreature(which);
  482.     break;
  483.     case MONKEY:
  484.         creature[which].dir      =
  485.         creature[which].pos      = 0;
  486.     break;
  487.     case ELEPHANT:
  488.         creature[which].pos      = 15; // -1 would also work
  489.     break;
  490.     case OCTOPUS:
  491.         creature[which].dir      =
  492.         creature[which].pos      = -1;
  493.     break;
  494.     case DOG:
  495.         creature[which].pos      = -1;
  496.         creature[which].dormant  = DORMANT; /* dormant */
  497.     break;
  498.     case ORB:
  499.         creature[which].deltax   = (arand(1) * 2) - 1;
  500.         creature[which].deltay   = (arand(1) * 2) - 1;
  501.     break;
  502.     case RAIN:
  503.         effect(FXBORN_RAIN);
  504.     break;
  505.     case CYCLONE_C:
  506.         effect(FXGET_CYCLONE);
  507.     break;
  508.     case MISSILE_C:
  509.         effect(FXBORN_MISSILE);
  510.         creature[which].frame    = 0;
  511.     break;
  512.     case BIRD:
  513.         creature[which].frame    = 0;
  514.         creature[which].dir      = 1;
  515.     break;
  516.     case SPIDER:
  517.         creature[which].last     = FROST;
  518.     break;
  519.     case OTTER:
  520.         if (x == 0)
  521.         {   creature[which].going    = OTTER_DOWN;
  522.             creature[which].journey  = OTTER_RIGHT;
  523.         } else
  524.         {   creature[which].going    = OTTER_UP;
  525.             creature[which].journey  = OTTER_LEFT;
  526.         }
  527.         creature[which].last       =
  528.         creature[which].oldlast    = STONE;
  529.     break;
  530.     case CAMEL:
  531.         creature[which].subspecies = arand(LASTOBJECT);
  532.     break;
  533.     case FRAGMENT:
  534.         if (creature[which].subspecies == BANANA)
  535.         {   creature[which].player = arand(3);
  536.             creature[which].score  = POINTS_BANANA;
  537.             creature[which].frame  = 0;
  538.             if (!arand(1))
  539.             {   creature[which].dir = 1;
  540.             } else
  541.             {   creature[which].dir = -1;
  542.         }   }
  543.     break;
  544.     case BULL:
  545.         if (!arand(1))
  546.         {   creature[which].dir    = 1;
  547.             draw(x, y, BULLRIGHT);
  548.         } else
  549.         {   creature[which].dir    = -1;
  550.             draw(x, y, BULLLEFT);
  551.         }
  552.         field[x][y] = BULL;
  553.     break;
  554.     case RABBIT:
  555.         if (deltax == 1)
  556.         {   draw(x, y, RABBITRIGHT);
  557.         } else
  558.         {   assert(deltax == -1);
  559.             draw(x, y, RABBITLEFT);
  560.         }
  561.         // no need to worry about .dir, it is not used for rabbits
  562.         field[x][y] = RABBIT;
  563.     break;
  564.     case FROG:
  565.         if (!arand(2))
  566.         {   creature[which].dir    = 1;
  567.             draw(x, y, FROGRIGHT);
  568.         } else
  569.         {   creature[which].dir    = -1;
  570.             draw(x, y, FROGLEFT);
  571.         }
  572.         field[x][y] = FROG;
  573.     break;
  574.     default:
  575.     break;
  576.     }
  577.  
  578.     if (creature[which].visible)
  579.     {   drawcreature(which);
  580.     }
  581.  
  582.     if (level > 5 && creature[which].speed >= 2)
  583.         creature[which].speed--;
  584.     if (level > 10 && creature[which].speed >= 2)
  585.         creature[which].speed--;
  586.     if (level > 15 && creature[which].speed >= 2)
  587.         creature[which].speed--;
  588.     if (level > 20 && creature[which].speed >= 2)
  589.         creature[which].speed--;
  590. }
  591.  
  592. AGLOBAL void creatureloop(SBYTE which)
  593. {   UBYTE bestdistance, c, i, distance, player;
  594.     SBYTE x, xx, xxx, xmin, xmax, frontx, rearx,
  595.           y, yy, yyy, ymin, ymax, fronty, reary;
  596.     FLAG  done;
  597.  
  598.     x = creature[which].x;
  599.     y = creature[which].y;
  600.  
  601.     if (!valid(x, y)) // defensive programming
  602.     {   creature[which].alive = FALSE;
  603.         return;
  604.  
  605.         /* TEXT temp1[SAYLIMIT + 1], temp2[8];
  606.  
  607.         strcpy(temp1, "BAD CREATURE AT x: ");
  608.         stci_d(temp2, x);
  609.         strcat(temp1, temp2);
  610.         strcat(temp1, ", y: ");
  611.         stci_d(temp2, y);
  612.         strcat(temp1, temp2);
  613.         strcat(temp1, "!");
  614.         say(temp1, PURPLE);
  615.         draw(fieldx + 1, 0, creature[which].species); // indicates which creature
  616.         Delay(250);
  617.         clearkybd();
  618.         anykey(FALSE); */
  619.     }
  620.  
  621.     /* decide whether and where to move */
  622.  
  623.     switch(creature[which].species)
  624.     {
  625.     case BIRD:
  626.         if (creature[which].player == 255)
  627.         {   bestdistance = 255;
  628.             for (player = 0; player <= 3; player++)
  629.             {   if (worm[player].lives)
  630.                 {   xx = abs(worm[player].x - x);
  631.                     yy = abs(worm[player].y - y);
  632.                     if (xx > yy)
  633.                         distance = xx;
  634.                     else distance = yy;
  635.                     if (distance <= DISTANCE_BIRD && distance < bestdistance)
  636.                     {   effect(FXBORN_BIRD);
  637.                         bestdistance = distance;
  638.                         creature[which].player = player;
  639.         }   }   }   }
  640.         if (creature[which].player != 255) // if swooping
  641.         {   if (worm[creature[which].player].lives)
  642.             {   creature[which].deltax = bsign(worm[creature[which].player].x - x);
  643.                 creature[which].deltay = bsign(worm[creature[which].player].y - y);
  644.             } else
  645.             {   creature[which].player = 255; // return to dormancy
  646.                 creature[which].deltax = creature[which].deltay = 0;
  647.         }   }
  648.     break;
  649.     case CAMEL:
  650.         xx = x + creature[which].deltax;
  651.         yy = y + creature[which].deltay;
  652.         if
  653.         (   !arand(FREQ_CAMELTURN)
  654.          || ((!creature[which].deltax) && (!creature[which].deltay))
  655.          || !valid(xx, yy)
  656.          || field[xx][yy] < FIRSTEMPTY
  657.          || field[xx][yy] > LASTEMPTY
  658.         )
  659.         {   do
  660.             {   xx = arand(2) - 1;
  661.                 yy = arand(2) - 1;
  662.             } while (!valid(x + xx, y + yy));
  663.             c = field[x + xx][y + yy];
  664.             if (c >= FIRSTEMPTY && c <= LASTEMPTY)
  665.             {   creature[which].deltax = xx;
  666.                 creature[which].deltay = yy;
  667.             } else
  668.             {   creature[which].deltax = 0;
  669.                 creature[which].deltay = 0;
  670.         }   }
  671.         if
  672.         (   (creature[which].deltax || creature[which].deltay)
  673.          && (!arand(FREQ_CAMELDROP))
  674.         )
  675.         {   creature[which].last = creature[which].subspecies;
  676.         } else creature[which].last = EMPTY;
  677.     break;
  678.     case CLOUD:
  679.         if
  680.         (   creature[which].x == 0
  681.          || creature[which].x == fieldx
  682.          || field[x + creature[which].deltax][y + creature[which].deltay] == METAL
  683.          || field[x + creature[which].deltax][y + creature[which].deltay] == STONE
  684.          || field[x + creature[which].deltax][y + creature[which].deltay] == WOOD
  685.         )
  686.         {   creature[which].deltax = -creature[which].deltax;
  687.         }
  688.     break;
  689.     case DOG:
  690.         /* remove a movement from the dog queue */
  691.  
  692.         if (creature[which].dormant == CHASING)
  693.         {   if (creature[which].pos != -1)
  694.             {   creature[which].deltax = thedogqueue[which][0].deltax;
  695.                 creature[which].deltay = thedogqueue[which][0].deltay;
  696.                 if (--creature[which].pos != -1)
  697.                 {   for (i = 0; i <= creature[which].pos; i++)
  698.                     {   thedogqueue[which][i].deltax = thedogqueue[which][i + 1].deltax;
  699.                         thedogqueue[which][i].deltay = thedogqueue[which][i + 1].deltay;
  700.             }   }   }
  701.             else creature[which].alive = FALSE;
  702.         }
  703.     break;
  704.     case BEAR:
  705.     case FISH:
  706.         do
  707.         {   xx = arand(2) - 1;
  708.             yy = arand(2) - 1;
  709.         } while (!valid(x + xx, y + yy));
  710.         c = field[x + xx][y + yy];
  711.         if
  712.         (   c == SLIME
  713.          || c == WOOD
  714.          || c == STONE
  715.          || c == METAL
  716.          || (c >= FIRSTTAIL && c <= LASTTAIL)
  717.          || (c >= FIRSTGLOW && c <= LASTGLOW)
  718.         )
  719.         {   creature[which].deltax = xx;
  720.             creature[which].deltay = yy;
  721.             creature[which].last = creature[which].oldlast;
  722.  
  723.             if (creature[which].species == FISH)
  724.             {   if (c >= FIRSTTAIL && c <= LASTTAIL)
  725.                 {   creature[which].oldlast = c - FIRSTTAIL + FIRSTGLOW;
  726.                 } else creature[which].oldlast = c;
  727.             } else
  728.             {   assert(creature[which].species == BEAR);
  729.                 if (c == STONE)
  730.                 {   creature[which].oldlast = METAL;
  731.                 } elif (c == WOOD)
  732.                 {   creature[which].oldlast = STONE;
  733.                 } elif (c >= FIRSTTAIL && c <= LASTTAIL)
  734.                 {   creature[which].oldlast = WOOD;
  735.                 } elif (c >= FIRSTGLOW && c <= LASTGLOW)
  736.                 {   creature[which].oldlast = c - FIRSTGLOW + FIRSTTAIL;
  737.                 } else
  738.                 {   creature[which].oldlast = c;
  739.         }   }   }
  740.         else
  741.         {   creature[which].deltax =
  742.             creature[which].deltay = 0;
  743.         }
  744.     break;
  745.     case GOOSE:
  746.         i = arand(3);
  747.         switch(i)
  748.         {
  749.         case 0:
  750.             creature[which].deltax = -1;
  751.             creature[which].deltay = 0;
  752.         break;
  753.         case 1:
  754.             creature[which].deltax = 1;
  755.             creature[which].deltay = 0;
  756.         break;
  757.         case 2:
  758.             creature[which].deltax = 0;
  759.             creature[which].deltay = -1;
  760.         break;
  761.         case 3:
  762.             creature[which].deltax = 0;
  763.             creature[which].deltay = 1;
  764.         break;
  765.         default:
  766.         assert(0);
  767.         break;
  768.         }
  769.     break;
  770.     case HORSE:
  771.         if (!arand(FREQ_HORSETURN))
  772.         {   if (!arand(1))
  773.             {    if (creature[which].dir == 0)
  774.                 {   creature[which].dir = 7;
  775.                 } else
  776.                 {   creature[which].dir--;
  777.         }    }
  778.             else
  779.             {    if (creature[which].dir == 7)
  780.                 {   creature[which].dir = 0;
  781.                 } else
  782.                 {   creature[which].dir++;
  783.             }    }
  784.  
  785.             turncreature(which);
  786.         }
  787.             break;
  788.     case KANGAROO:
  789.         creature[which].deltax = bsign(creature[which].deltax);
  790.         creature[which].deltay = bsign(creature[which].deltay);
  791.         if
  792.         (   ((!creature[which].deltax) && (!creature[which].deltay))
  793.          || !arand(FREQ_KANGAROOTURN)
  794.         )
  795.         {   do
  796.             {   xx = arand(2) - 1;
  797.                 yy = arand(2) - 1;
  798.             } while (!valid(x + xx, y + yy));
  799.             c = field[x + xx][y + yy];
  800.             if (c >= FIRSTEMPTY && c <= LASTEMPTY)
  801.             {   creature[which].deltax = xx;
  802.                 creature[which].deltay = yy;
  803.             } else
  804.             {   creature[which].deltax = 0;
  805.                 creature[which].deltay = 0;
  806.         }   }
  807.         else
  808.         {   c = field[xwrap(x + creature[which].deltax)][ywrap(y + creature[which].deltay)];
  809.             if (c < FIRSTEMPTY || c > LASTEMPTY)
  810.             {   c = field[xwrap(x + (creature[which].deltax * 2))][ywrap(y + (creature[which].deltay * 2))];
  811.                 if (c >= FIRSTEMPTY && c <= LASTEMPTY)
  812.                 {   creature[which].deltax *= 2;
  813.                     creature[which].deltay *= 2;
  814.                 } else
  815.                 {   c = field[xwrap(x - creature[which].deltax)][ywrap(y - creature[which].deltay)];
  816.                     if (c >= FIRSTEMPTY && c <= LASTEMPTY)
  817.                     {   creature[which].deltax = -creature[which].deltax;
  818.                         creature[which].deltay = -creature[which].deltay;
  819.                     } else
  820.                     {   creature[which].deltax =
  821.                         creature[which].deltay = 0;
  822.         }   }   }   }
  823.     break;
  824.     case MISSILE_C:
  825.         bestdistance = 255;
  826.         for (player = 0; player <= 3; player++)
  827.         {   if (creature[which].player != player && worm[player].lives)
  828.             {   xx = abs(worm[player].x - x);
  829.                 yy = abs(worm[player].y - y);
  830.                 if (xx < yy)
  831.                 {   distance = xx;
  832.                 } else distance = yy;
  833.                 if (distance < bestdistance)
  834.                 {   bestdistance = distance;
  835.                     creature[which].deltax = bsign(worm[player].x - x);
  836.                     creature[which].deltay = bsign(worm[player].y - y);
  837.             }   }
  838.             for (i = 0; i <= CREATURES; i++)
  839.             {   if
  840.                 (   creature[i].alive
  841.                  && which != i
  842.                  && creature[i].player != player
  843.                 )
  844.                 {   xx = abs(creature[i].x - x);
  845.                     yy = abs(creature[i].y - y);
  846.                     if (xx < yy)
  847.                     {   distance = xx;
  848.                     } else distance = yy;
  849.                     if (distance < bestdistance)
  850.                     {   bestdistance = distance;
  851.                         creature[which].deltax = bsign(creature[i].x - x);
  852.                         creature[which].deltay = bsign(creature[i].y - y);
  853.         }   }   }   }
  854.         if (bestdistance == 255)
  855.         {   creature[which].alive = FALSE;
  856.             change(x, y, EMPTY);
  857.         }
  858.     break;
  859.     case MONKEY:
  860.         creature[which].pos += creature[which].dir;
  861.         if (creature[which].pos == 0) // monkey never stops moving
  862.         {   choosediagonal(which);
  863.             creature[which].dir = 1;
  864.         } elif (creature[which].pos == 5)
  865.         {   creature[which].deltax = -creature[which].deltax;
  866.             creature[which].deltay = -creature[which].deltay;
  867.             creature[which].dir = -1;
  868.         }
  869.     break;
  870.     case ORB:
  871.         frontx  = xwrap(x + creature[which].deltax);  /* look in front */
  872.         fronty  = ywrap(y + creature[which].deltay);
  873.         rearx   = xwrap(x - creature[which].deltax);  /* look behind */
  874.         reary   = ywrap(y - creature[which].deltay);
  875.         if (bouncecreature(which, frontx, fronty))
  876.         {   bounceoffcreature(which, frontx, fronty);
  877.             xx = -creature[which].deltax; /* default bounce angle is 180° */
  878.             yy = -creature[which].deltay;
  879.             if (!bouncecreature(which, frontx, reary))
  880.             {   if (bouncecreature(which, rearx, fronty))
  881.                 {   bounceoffcreature(which, rearx, fronty);
  882.                     xx = creature[which].deltax;
  883.             }   }
  884.             elif (!bouncecreature(which, rearx, fronty))
  885.             {   bounceoffcreature(which, rearx, fronty);
  886.                 yy = creature[which].deltay;
  887.             }
  888.             creature[which].deltax = xx;
  889.             creature[which].deltay = yy;
  890.         }
  891.     break;
  892.     case OTTER:
  893.         if (secondsleft)
  894.         {   return;
  895.         }
  896.         if (creature[which].journey == OTTER_RIGHT)
  897.         {   switch(creature[which].going)
  898.             {
  899.             case OTTER_DOWN:
  900.                 if (creature[which].y == fieldy)
  901.                 {   if (creature[which].x == fieldx)
  902.                     {   creature[which].journey = OTTER_LEFT;
  903.                         creature[which].going = OTTER_UP;
  904.                     } else
  905.                     {   creature[which].going = OTTER_RIGHT;
  906.                         creature[which].then  = OTTER_UP;
  907.                 }   }
  908.             break;
  909.             case OTTER_RIGHT:
  910.                 creature[which].going = creature[which].then;
  911.             break;
  912.             case OTTER_UP:
  913.                 if (creature[which].y == 0)
  914.                 {   if (creature[which].x == fieldx)
  915.                     {   creature[which].journey = OTTER_LEFT;
  916.                         creature[which].going = OTTER_DOWN;
  917.                     } else
  918.                     {   creature[which].going = OTTER_RIGHT;
  919.                         creature[which].then  = OTTER_DOWN;
  920.                 }   }
  921.             break;
  922.             default:
  923.             break;
  924.         }   }
  925.         else
  926.         {   assert(creature[which].journey == OTTER_LEFT);
  927.             switch(creature[which].going)
  928.             {
  929.             case OTTER_DOWN:
  930.                 if (creature[which].y == fieldy)
  931.                 {   if (creature[which].x == 0)
  932.                     {   creature[which].journey = OTTER_RIGHT;
  933.                         creature[which].going = OTTER_UP;
  934.                     } else
  935.                     {   creature[which].going = OTTER_LEFT;
  936.                         creature[which].then  = OTTER_UP;
  937.                 }   }
  938.             break;
  939.             case OTTER_LEFT:
  940.                 creature[which].going = creature[which].then;
  941.             break;
  942.             case OTTER_UP:
  943.                 if (creature[which].y == 0)
  944.                 {   if (creature[which].x == 0)
  945.                     {   creature[which].journey = OTTER_RIGHT;
  946.                         creature[which].going = OTTER_DOWN;
  947.                     } else
  948.                     {   creature[which].going = OTTER_LEFT;
  949.                         creature[which].then  = OTTER_DOWN;
  950.                 }   }
  951.             break;
  952.             default:
  953.                 assert(0);
  954.             break;
  955.         }   }
  956.  
  957.         if (creature[which].going == OTTER_RIGHT)
  958.         {   creature[which].deltax = 1;
  959.             creature[which].deltay = 0;
  960.         } elif (creature[which].going == OTTER_LEFT)
  961.         {   creature[which].deltax = -1;
  962.             creature[which].deltay = 0;
  963.         } elif (creature[which].going == OTTER_UP)
  964.         {   creature[which].deltax = 0;
  965.             creature[which].deltay = -1;
  966.         } elif (creature[which].going == OTTER_DOWN)
  967.         {   creature[which].deltax = 0;
  968.             creature[which].deltay = 1;
  969.         }
  970.     break;
  971.     case ELEPHANT:
  972.         /* 01234
  973.            F   5
  974.            E   6
  975.            D   7
  976.            CBA98 */
  977.  
  978.         if (creature[which].pos == 15)
  979.         {   creature[which].pos = 0;
  980.         } else creature[which].pos++;
  981.  
  982.         if (creature[which].pos == 0)
  983.         {   creature[which].deltax =  1;
  984.             creature[which].deltay =  0;
  985.         } elif (creature[which].pos == 4)
  986.         {   creature[which].deltax =  0;
  987.             creature[which].deltay =  1;
  988.         } elif (creature[which].pos == 8)
  989.         {   creature[which].deltax = -1;
  990.             creature[which].deltay =  0;
  991.         } elif (creature[which].pos == 12)
  992.         {   creature[which].deltax =  0;
  993.             creature[which].deltay = -1;
  994.         }
  995.     break;
  996.     case ANT:
  997.     do
  998.         {   xx = arand(2) - 1;
  999.             yy = arand(2) - 1;
  1000.         } while (!valid(x + xx, y + yy));
  1001.         if (xx == 0 && yy == 0)
  1002.         {   if (valid(x + creature[which].deltax, y + creature[which].deltay))
  1003.             {   xx = creature[which].deltax;
  1004.                 yy = creature[which].deltay;
  1005.             } else
  1006.             {   xx = -creature[which].deltax;
  1007.                 yy = -creature[which].deltay;
  1008.         }   }
  1009.         creature[which].deltax = xx;
  1010.         creature[which].deltay = yy;
  1011.     break;
  1012.     case CYCLONE_C:
  1013.         /* Cyclones have a slight upwards drift.
  1014.         Higher values of WEIGHT make them less buoyant. */
  1015.  
  1016.         creature[which].deltax = arand(2) - 1;
  1017.         if (!arand(WEIGHT))
  1018.             creature[which].deltay = arand(1) - 1;
  1019.         else creature[which].deltay = arand(2) - 1;
  1020.     break;
  1021.     case RABBIT:
  1022.         xx = x + creature[which].deltax;
  1023.         done = FALSE;
  1024.         do
  1025.         {    if (!valid(xx, y))
  1026.             {   creature[which].alive = FALSE;
  1027.                 change(x, y, EMPTY);
  1028.                 done = TRUE;
  1029.             } elif
  1030.             (   field[xx][y] <= LASTOBJECT
  1031.              || (field[xx][y] >= FIRSTEMPTY && field[xx][y] <= LASTEMPTY)
  1032.              )
  1033.             {   creature[which].x = xx;
  1034.                 done = TRUE;
  1035.              } else
  1036.             {    xx += creature[which].deltax;
  1037.         }   }
  1038.         while (!done);
  1039.     break;
  1040.     case MOUSE:
  1041.         bestdistance = 255;
  1042.         if (x - DISTANCE_MOUSE < 0)
  1043.         {    xmin = 0;
  1044.         } else xmin = x - DISTANCE_MOUSE;
  1045.         if (x + DISTANCE_MOUSE > fieldx)
  1046.         {    xmax = fieldx;
  1047.         } else xmax = x + DISTANCE_MOUSE;
  1048.         if (y - DISTANCE_MOUSE < 0)
  1049.         {    ymin = 0;
  1050.         } else ymin = y - DISTANCE_MOUSE;
  1051.         if (y + DISTANCE_MOUSE > fieldy)
  1052.         {    ymax = fieldy;
  1053.         } else ymax = y + DISTANCE_MOUSE;
  1054.  
  1055.         for (xx = xmin; xx <= xmax; xx++)
  1056.         {    for (yy = ymin; yy <= ymax; yy++)
  1057.             {    assert(valid(xx, yy));
  1058.                 if (field[xx][yy] <= LASTOBJECT)
  1059.                 {    xxx = abs(xx - x);
  1060.                     yyy = abs(yy - y);
  1061.                     if (xxx < yyy)
  1062.                     {   distance = xxx;
  1063.                     } else distance = yyy;
  1064.                     if (distance < bestdistance)
  1065.                     {   bestdistance = distance;
  1066.                         creature[which].deltax = bsign(xx - x);
  1067.                         creature[which].deltay = bsign(yy - y);
  1068.         }    }   }    }
  1069.         if (bestdistance == 255)
  1070.         {   creature[which].deltax =
  1071.             creature[which].deltay = 0;
  1072.         }
  1073.     break;
  1074.     case SNAIL:
  1075.         xx = creature[which].deltax;
  1076.         yy = creature[which].deltay;
  1077.         if
  1078.         (   (!valid(x + xx, y + yy))
  1079.          || (xx == 0 && yy == 0)
  1080.          || (field[x + xx][y + yy] > LASTOBJECT && (field[x + xx][y + yy] < FIRSTEMPTY || field[x + xx][y + yy] > LASTEMPTY))
  1081.         )
  1082.         {   do
  1083.             {   xx = arand(2) - 1;
  1084.                 yy = arand(2) - 1;
  1085.             } while (!valid(x + xx, y + yy));
  1086.             if
  1087.             (    field[x + xx][y + yy] <= LASTOBJECT
  1088.              || (field[x + xx][y + yy] >= FIRSTEMPTY && field[x + xx][y + yy] <= LASTEMPTY)
  1089.              )
  1090.             {   creature[which].deltax = xx;
  1091.                 creature[which].deltay = yy;
  1092.             } else
  1093.             {   creature[which].deltax = 0;
  1094.                             creature[which].deltay = 0;
  1095.         }   }
  1096.     break;
  1097.     case SPIDER:
  1098.         xx = creature[which].deltax;
  1099.         yy = creature[which].deltay;
  1100.         if
  1101.         (   (!valid(x + xx, y + yy))
  1102.          || (xx == 0 && yy == 0)
  1103.          || (field[x + xx][y + yy] > LASTOBJECT && (field[x + xx][y + yy] < FIRSTEMPTY || field[x + xx][y + yy] > LASTEMPTY))
  1104.          || (!arand(FREQ_SPIDERTURN))
  1105.         )
  1106.         {   do
  1107.             {   xx = arand(2) - 1;
  1108.                 yy = arand(2) - 1;
  1109.             } while (!valid(x + xx, y + yy));
  1110.             if
  1111.             (   field[x + xx][y + yy] <= LASTOBJECT
  1112.              || (field[x + xx][y + yy] >= FIRSTEMPTY && field[x + xx][y + yy] <= LASTEMPTY)
  1113.              ||  field[x + xx][y + yy] == FROST // so that spiders can traverse their own webs
  1114.             )
  1115.             {   creature[which].deltax = xx;
  1116.                 creature[which].deltay = yy;
  1117.             } else
  1118.             {   creature[which].deltax = 0;
  1119.                 creature[which].deltay = 0;
  1120.         }   }
  1121.     break;
  1122.     case FROG:
  1123.         if (creature[which].deltax != 0 || creature[which].deltay != 0)
  1124.         {   creature[which].deltax = 0;
  1125.             creature[which].deltay = 0;
  1126.         } elif (creature[which].dormant == 0 && !arand(FREQ_FROGMOVE))
  1127.         {   xx = arand(6) - 3;
  1128.             yy = arand(6) - 3;
  1129.             if
  1130.             (   (xx != 0 || yy != 0)
  1131.              && valid(x + xx, y + yy)
  1132.              && field[x + xx][y + yy] >= FIRSTEMPTY
  1133.              && field[x + xx][y + yy] <= LASTEMPTY
  1134.             )
  1135.             {   creature[which].deltax = xx;
  1136.                 creature[which].deltay = yy;
  1137.                 if (!arand(1))
  1138.                 {   creature[which].dir = -1;
  1139.                 } else
  1140.                 {   creature[which].dir = 1;
  1141.         }   }   }
  1142.     break;
  1143.     case SALAMANDER:
  1144.         // this is a workaround for a very strange bug
  1145.         choosediagonal(which);
  1146.     break;
  1147.     default: // octopus, giraffe, fragment, bull
  1148.     break;
  1149.     }
  1150.  
  1151.     /* now move */
  1152.  
  1153.     if (creature[which].deltax || creature[which].deltay)
  1154.     {   if (creature[which].visible)
  1155.         {   /* erase previous image */
  1156.             if
  1157.             (   (creature[which].last >= FIRSTTAIL && creature[which].last <= LASTTAIL)
  1158.              || (creature[which].last >= FIRSTGLOW && creature[which].last <= LASTGLOW)
  1159.             )
  1160.             {   field[x][y] = creature[which].last;
  1161.                 if (tailfield[x][y] < FIRSTMAGIC)
  1162.                 {   drawtail(x, y, tailfield[x][y] + ((creature[which].last - FIRSTGLOW) * SECONDMAGIC) + FIRSTMAGIC);
  1163.                 } else
  1164.                 {   drawtail(x, y, tailfield[x][y] + ((creature[which].last - FIRSTGLOW) * SECONDMAGIC));
  1165.             }   }
  1166.             else
  1167.             {   change(x, y, creature[which].last);
  1168.             }
  1169.             if (creature[which].species == OTTER)
  1170.             {   creature[which].last = STONE;
  1171.             } elif (creature[which].species == SPIDER)
  1172.             {   creature[which].last = FROST;
  1173.             } elif (creature[which].species == GOOSE)
  1174.             {   creature[which].last = GOLD;
  1175.             }  else
  1176.             {   creature[which].last = EMPTY;
  1177.         }   }
  1178.     if (creature[which].alive)
  1179.     {   creature[which].x += creature[which].deltax;
  1180.         creature[which].y += creature[which].deltay;
  1181.         if
  1182.             (   creature[which].species == ORB
  1183.              || creature[which].species == HORSE
  1184.              || creature[which].species == MONKEY
  1185.             )
  1186.         {   creature[which].x = xwrap(creature[which].x);
  1187.             creature[which].y = ywrap(creature[which].y);
  1188.             } elif (!valid(creature[which].x, creature[which].y))
  1189.             {   creature[which].alive = FALSE;
  1190.     }   }   }
  1191.  
  1192.     creature[which].visible = TRUE;
  1193.     x = creature[which].x;
  1194.     y = creature[which].y;
  1195.  
  1196.     /* Collision detection. */
  1197.  
  1198.     if
  1199.     (    creature[which].alive
  1200.      &&  creature[which].species != FISH
  1201.      &&  creature[which].species != BEAR
  1202.      &&  creature[which].species != GIRAFFE
  1203.      && (creature[which].deltax || creature[which].deltay)
  1204.     )
  1205.     {   c = field[x][y];
  1206.  
  1207.         if (c >= FIRSTHEAD && c <= LASTHEAD)
  1208.         {   wormcreature(c - FIRSTHEAD, which);
  1209.         } elif (c >= FIRSTPROTECTOR && c <= LASTPROTECTOR)
  1210.         {   protcreature(c - FIRSTPROTECTOR, which);
  1211.         } elif (c >= FIRSTTAIL && c <= LASTTAIL)
  1212.         {   ;
  1213.         } elif
  1214.         (   (c >= FIRSTNUMBER && c <= LASTNUMBER)
  1215.          || (c >= FIRSTGRAVE  && c <= LASTGRAVE )
  1216.          ||  c == FROGTONGUE
  1217.          ||  c == START
  1218.         )
  1219.         {   creature[which].alive = FALSE;
  1220.         } elif (c >= FIRSTCREATURE)
  1221.         {   i = whichcreature(x, y, c, which);
  1222.             creaturecreature(which, i);
  1223.         } elif
  1224.         (   c == METAL
  1225.          || c == STONE
  1226.          || c == WOOD
  1227.         )
  1228.         {   if (!creatureinfo[creature[which].species - FIRSTCREATURE].wall)
  1229.             {   if (creature[which].species == FRAGMENT && c == METAL)
  1230.                 {   effect(FXUSE_ARMOUR);
  1231.                     reflect(which);
  1232.                 } elif
  1233.                 (   creature[which].species != OTTER
  1234.                  && creature[which].species != CYCLONE_C
  1235.                  && creature[which].species != ANT
  1236.                  && creature[which].species != MISSILE_C
  1237.                 )
  1238.                 {   creature[which].alive = FALSE;
  1239.         }   }   }
  1240.         elif (c == TELEPORT)
  1241.         {   i = whichteleport(x, y);
  1242.             if (blockedtel(i, creature[which].deltax, creature[which].deltay))
  1243.                 creature[which].alive = FALSE;
  1244.             else
  1245.             {   effect(FXUSE_TELEPORT);
  1246.                 creature[which].x = teleport[partner(i)].x + creature[which].deltax;
  1247.                 creature[which].y = teleport[partner(i)].y + creature[which].deltay;
  1248.  
  1249.                 if (creature[which].species == ORB)
  1250.                 {   creature[which].x = xwrap(creature[which].x);
  1251.                     creature[which].y = ywrap(creature[which].y);
  1252.                 } else
  1253.                 {   if (!(valid(creature[which].x, creature[which].y)))
  1254.                         creature[which].alive = FALSE;
  1255.                     if (creature[which].species == FRAGMENT)
  1256.                         creature[which].last = SILVER;
  1257.         }   }   }
  1258.         elif (c <= LASTOBJECT && creature[which].species != MOUSE)
  1259.         {   switch (c)
  1260.             {
  1261.             case MINIBOMB:
  1262.                 drawcreature(which);
  1263.                 bombblast(ORB, which, x, y, FALSE);
  1264.             break;
  1265.             case SUPERBOMB:
  1266.                 drawcreature(which);
  1267.                 bombblast(ORB, which, x, y, TRUE);
  1268.             break;
  1269.             case PROTECTOR:
  1270.                 effect(FXGET_OBJECT);
  1271.                 for (player = 0; player <= 3; player++)
  1272.                 {   if (worm[player].lives)
  1273.                     {   for (i = 0; i <= PROTECTORS; i++)
  1274.                         {  if (protector[player][i].alive)
  1275.                            {   protector[player][i].alive = FALSE;
  1276.                                if (protector[player][i].visible)
  1277.                                {   change(protector[player][i].x, protector[player][i].y, EMPTY);
  1278.                 }   }   }  }   }
  1279.             break;
  1280.             case MISSILE_O:
  1281.                 effect(FXGET_OBJECT);
  1282.                 for (i = 0; i <= CREATURES; i++)
  1283.                 {   if (creature[i].alive && creature[i].species == MISSILE_C)
  1284.                     {   creature[i].alive = FALSE;
  1285.                         change(x, y, EMPTY);
  1286.                 }   }
  1287.             break;
  1288.             case MULTIPLIER:
  1289.                 effect(FXGET_OBJECT);
  1290.                 for (player = 0; player <= 3; player++)
  1291.                 {   if (worm[player].lives)
  1292.                     {   worm[player].multi = 1;
  1293.                         stat(player, BONUS);
  1294.                 }   }
  1295.             break;
  1296.             case AFFIXER:
  1297.                 effect(FXGET_OBJECT);
  1298.                 for (player = 0; player <= 3; player++)
  1299.                     if (worm[player].lives)
  1300.                     {   worm[player].affixer = FALSE;
  1301.                         icon(player, AFFIXER);
  1302.                     }
  1303.             break;
  1304.             case REMNANTS:
  1305.                 effect(FXGET_OBJECT);
  1306.                 for (player = 0; player <= 3; player++)
  1307.                     if (worm[player].lives)
  1308.                     {   worm[player].remnants = FALSE;
  1309.                         icon(player, REMNANTS);
  1310.                     }
  1311.             break;
  1312.             case SIDESHOT:
  1313.                 effect(FXGET_POWERUP);
  1314.                 for (player = 0; player <= 3; player++)
  1315.                     if (worm[player].lives)
  1316.                     {   worm[player].sideshot = FALSE;
  1317.                         icon(player, SIDESHOT);
  1318.                     }
  1319.             break;
  1320.             case MAGNET:
  1321.                 effect(FXGET_OBJECT);
  1322.                 for (i = 0; i <= MAGNETS; i++)
  1323.                     if (magnet[i].alive)
  1324.                         magnet[i].alive = FALSE;
  1325.             break;
  1326.             case PUSHER:
  1327.                 effect(FXGET_OBJECT);
  1328.                 for (i = 0; i <= 3; i++)
  1329.                     if (worm[i].lives && worm[i].pusher)
  1330.                     {   worm[i].pusher = FALSE;
  1331.                         icon(i, PUSHER);
  1332.                     }
  1333.                 break;
  1334.             case ENCLOSER:
  1335.                 effect(FXGET_OBJECT);
  1336.                 for (i = 0; i <= 3; i++)
  1337.                 {   if (worm[i].lives && worm[i].encloser)
  1338.                     {   worm[i].encloser = FALSE;
  1339.                         icon(i, ENCLOSER);
  1340.                 }   }
  1341.             break;
  1342.             case GLOW:
  1343.                 effect(FXGET_OBJECT);
  1344.                 for (xx = 0; xx <= fieldx; xx++)
  1345.                     for (yy = 0; yy <= fieldy; yy++)
  1346.                         if (field[xx][yy] >= FIRSTGLOW && field[xx][yy] <= LASTGLOW)
  1347.                             change(xx, yy, EMPTY);
  1348.             break;
  1349.             case SWITCHER:
  1350.                 effect(FXGET_OBJECT);
  1351.                 for (xx = 0; xx <= fieldx; xx++)
  1352.                     for (yy = 0; yy <= fieldy; yy++)
  1353.                         if (field[xx][yy] >= FIRSTTAIL && field[xx][yy] <= LASTTAIL)
  1354.                             change(xx, yy, WOOD);
  1355.             break;
  1356.             case GROWER:
  1357.                 effect(FXGET_GROWER);
  1358.                 for (xx = 0; xx <= fieldx; xx++)
  1359.                     for (yy = 0; yy <= fieldy; yy++)
  1360.                         if (field[xx][yy] == WOOD)
  1361.                             for (xxx = xx - 1; xxx <= xx + 1; xxx++)
  1362.                                 for (yyy = yy - 1; yyy <= yy + 1; yyy++)                                                                if (valid(xxx, yyy) && field[xxx][yyy] == EMPTY)
  1363.                                     field[xxx][yyy] = TEMPWOOD;
  1364.                 for (xx = 0; xx <= fieldx; xx++)
  1365.                     for (yy = 0; yy <= fieldy; yy++)
  1366.                         if (field[xx][yy] == TEMPWOOD)
  1367.                             change(xx, yy, WOOD);
  1368.             break;
  1369.             case AUTOJUMP:
  1370.                 effect(FXGET_OBJECT);
  1371.                 for (player = 0; player <= 3; player++)
  1372.                     if (worm[player].lives)
  1373.                     {   worm[player].autojump = FALSE;
  1374.                         icon(player, AUTOJUMP);
  1375.                     }
  1376.             break;
  1377.             case CUTTER:
  1378.                 effect(FXGET_OBJECT);
  1379.                 for (i = 0; i <= 3; i++)
  1380.                     if (worm[i].lives && worm[i].cutter)
  1381.                     {   worm[i].cutter = 0;
  1382.                         icon(i, CUTTER);
  1383.                     }
  1384.             break;
  1385.             default:
  1386.                 effect(FXGET_OBJECT);
  1387.                 creature[which].speed = speedup(creature[which].speed, FALSE);
  1388.             break;
  1389.     }   }   }
  1390.  
  1391.     x = creature[which].x; // These are refreshed in case a
  1392.     y = creature[which].y; // fragment has been reflected.
  1393.  
  1394.     if
  1395.     (   creature[which].alive
  1396.      && creature[which].visible
  1397.      && (creature[which].deltax || creature[which].deltay)
  1398.     )
  1399.     {   drawcreature(which);
  1400.     }
  1401.  
  1402.     if (creature[which].alive)
  1403.     {   /* decide whether to fire */
  1404.         switch(creature[which].species)
  1405.         {
  1406.         case CLOUD:
  1407.             if (!arand(FREQ_CLOUDFIRE))
  1408.             {   creaturebullet(x, y,  0, -1, FRAGMENT);
  1409.             }
  1410.             if (!arand(FREQ_CLOUDRAIN))
  1411.             {   if (creature[which].y != fieldy)
  1412.                 {   c = field[x][y + 1];
  1413.                     if (c >= FIRSTEMPTY && c <= LASTEMPTY)
  1414.                     {   for (i = 0; i <= CREATURES; i++)
  1415.                         {   if (!creature[i].alive)
  1416.                             {   createcreature(RAIN, i, x, y + 1, 0, 1, (UBYTE) ((r / 16) % 4), 0);
  1417.                                 break;
  1418.             }   }   }   }   }
  1419.         break;
  1420.         case KANGAROO:
  1421.             if (!arand(FREQ_KANGAROOFIRE))
  1422.             {   creaturebullet(x, y, -1, -1, FRAGMENT);
  1423.                 creaturebullet(x, y,  1, -1, FRAGMENT);
  1424.                 creaturebullet(x, y, -1,  1, FRAGMENT);
  1425.                 creaturebullet(x, y,  1,  1, FRAGMENT);
  1426.             }
  1427.         break;
  1428.         case ELEPHANT:
  1429.             if (creature[which].pos == 0 || creature[which].pos == 4)
  1430.             {   creaturebullet(x, y,  0, -1, FRAGMENT); // fire up
  1431.             }
  1432.             if (creature[which].pos == 0 || creature[which].pos == 12)
  1433.             {   creaturebullet(x, y, -1,  0, FRAGMENT); // fire left
  1434.             }
  1435.             if (creature[which].pos == 4 || creature[which].pos == 8)
  1436.             {   creaturebullet(x, y,  1,  0, FRAGMENT); // fire right
  1437.             }
  1438.             if (creature[which].pos == 8 || creature[which].pos == 12)
  1439.             {   creaturebullet(x, y,  0,  1, FRAGMENT); // fire down
  1440.             }
  1441.         break;
  1442.         case MONKEY:
  1443.             if (creature[which].pos == 5)
  1444.             {   chooseorthagonal(&xx, &yy);
  1445.                 creaturebullet(x, y, xx, yy, BANANA);
  1446.             }
  1447.         break;
  1448.         case OCTOPUS:
  1449.             if (creature[which].dir == -1)
  1450.             {   if (!arand(FREQ_OCTOPUSFIRE))
  1451.                 {   creature[which].dir = arand(7);
  1452.                     if (arand(1))
  1453.                     {   creature[which].tonguedir = 1;
  1454.                     } else
  1455.                     {   creature[which].tonguedir = -1;
  1456.                     }
  1457.                     creature[which].pos = -1;
  1458.             }   }
  1459.             elif (!arand(FREQ_OCTOPUSSPIN))
  1460.             {   for (i = 0; i <= CREATURES; i++)
  1461.                 {   if
  1462.                     (   creature[i].alive
  1463.                      && creature[i].species == OCTOPUS
  1464.                      && creature[i].dir     >= 0
  1465.                     )
  1466.                     {   for (i = 0; i <= CREATURES; i++)
  1467.                         {   if (!creature[i].alive)
  1468.                             {   switch(creature[which].dir)
  1469.                                 {
  1470.                                 case 0:
  1471.                                     xx = 0;
  1472.                                     yy = -1;
  1473.                                 break;
  1474.                                 case 1:
  1475.                                     xx = 1;
  1476.                                     yy = -1;
  1477.                                 break;
  1478.                                 case 2:
  1479.                                     xx = 1;
  1480.                                     yy = 0;
  1481.                                 break;
  1482.                                 case 3:
  1483.                                     xx = 1;
  1484.                                     yy = 1;
  1485.                                 break;
  1486.                                 case 4:
  1487.                                     xx = 0;
  1488.                                     yy = 1;
  1489.                                 break;
  1490.                                 case 5:
  1491.                                     xx = -1;
  1492.                                     yy = 1;
  1493.                                 break;
  1494.                                 case 6:
  1495.                                     xx = -1;
  1496.                                     yy = 0;
  1497.                                 break;
  1498.                                 case 7:
  1499.                                     xx = -1;
  1500.                                     yy = -1;
  1501.                                 break;
  1502.                                 default:
  1503.                                     assert(0);
  1504.                                     xx = yy = 0; // to avoid spurious warnings
  1505.                                 break;
  1506.                                 }
  1507.                                 xxx = x + xx;
  1508.                                 yyy = y + yy;
  1509.                                 if (valid(xxx, yyy))
  1510.                                 {   effect(FXBORN_FRAGMENT);
  1511.                                     createcreature(FRAGMENT, i, xxx, yyy, xx, yy, 255, FRAGMENT);
  1512.                                 }
  1513.                                 if (++creature[which].pos == 8)
  1514.                                 {   creature[which].pos = -1;
  1515.                                 } else
  1516.                                 {   if (creature[which].dir == 7 && creature[which].tonguedir == 1)
  1517.                                     {   creature[which].dir = 0;
  1518.                                     } elif (creature[which].dir == 0 && creature[which].tonguedir == -1)
  1519.                                     {   creature[which].dir = 7;
  1520.                                     } else
  1521.                                     {   creature[which].dir += creature[which].tonguedir;
  1522.                                 }   }
  1523.                                 break;
  1524.             }   }   }   }   }
  1525.         break;
  1526.         case SALAMANDER:
  1527.             if (!arand(FREQ_SALAMANDERFIRE))
  1528.             {   chooseorthagonal(&xx, &yy);
  1529.                 creaturebullet(x, y, xx, yy, FRAGMENT);
  1530.             }
  1531.         break;
  1532.         case FROG:
  1533.             if (creature[which].dormant == 0)
  1534.             {   if (!arand(FREQ_FROGFIRE))
  1535.                 {   creature[which].dormant = 1;
  1536.                     creature[which].tonguedir = 1;
  1537.                     creature[which].tonguex = x;
  1538.                     if (creature[which].dir == -1)
  1539.                     {   draw(x, y, FROGMOUTHLEFT);
  1540.                     } else
  1541.                     {   assert(creature[which].dir == 1);
  1542.                         draw(x, y, FROGMOUTHRIGHT);
  1543.             }   }   }
  1544.             else
  1545.             {   creature[which].dormant += creature[which].tonguedir;
  1546.                 if (creature[which].tonguedir == 1)
  1547.                 {   if (valid(creature[which].tonguex + creature[which].dir, y))
  1548.                     {   c = field[creature[which].tonguex + creature[which].dir][y];
  1549.                         if
  1550.                         (    c != TELEPORT
  1551.                          &&  c != METAL
  1552.                          &&  c != STONE
  1553.                          &&  c != WOOD
  1554.                          && (c < FIRSTPROTECTOR || c > LASTPROTECTOR)
  1555.                         )
  1556.                         {   creature[which].tonguex += creature[which].dir;
  1557.                             if (c >= FIRSTCREATURE)
  1558.                             {   creature[whichcreature(creature[which].tonguex, y, c, which)].alive = FALSE;
  1559.                                 change(creature[which].tonguex, y, FROGTONGUE);
  1560.                             } elif (c >= FIRSTHEAD && c <= LASTHEAD && worm[c - FIRSTHEAD].armour == 0)
  1561.                             {   worm[c - FIRSTHEAD].cause = FROG;
  1562.                                 worm[c - FIRSTHEAD].alive = FALSE;
  1563.                             } else
  1564.                             {   change(creature[which].tonguex, y, FROGTONGUE);
  1565.                         }   }
  1566.                         else
  1567.                         {   creature[which].tonguedir = -1;
  1568.                     }   }
  1569.                     else
  1570.                     {   creature[which].tonguedir = -1;
  1571.                 }   }
  1572.                 else
  1573.                 {   assert(creature[which].tonguedir == -1);
  1574.                     if (creature[which].dormant > 1)
  1575.                     {   if (field[creature[which].tonguex][y] == FROGTONGUE)
  1576.                         {   change(creature[which].tonguex, y, EMPTY);
  1577.                         }
  1578.                         creature[which].tonguex -= creature[which].dir;
  1579.                     } else
  1580.                     {   if (creature[which].dir == -1)
  1581.                         {   draw(x, y, FROGLEFT);
  1582.                         } else
  1583.                         {   assert(creature[which].dir == 1);
  1584.                             draw(x, y, FROGRIGHT);
  1585.             }   }   }   }
  1586.         break;
  1587.         default:
  1588.             // rabbits, snails, spiders, etc.
  1589.             // ie. creatures which do not fire
  1590.         break;
  1591. }   }   }
  1592.  
  1593. MODULE void creaturebullet(SBYTE x, SBYTE y, SBYTE deltax, SBYTE deltay, UBYTE subspecies)
  1594. {   UBYTE i, c;
  1595.  
  1596.     for (i = 0; i <= CREATURES; i++)
  1597.     {   if (!creature[i].alive)
  1598.         {   if (valid(x + deltax, y + deltay))
  1599.             {   c = field[x + deltax][y + deltay];
  1600.                 if
  1601.                 (   (c >= FIRSTEMPTY && c <= LASTEMPTY)
  1602.                 ||  (c >= FIRSTTAIL && c <= LASTTAIL)
  1603.                 )
  1604.                 {   effect(FXBORN_FRAGMENT);
  1605.                     createcreature(FRAGMENT, i, x + deltax, y + deltay, deltax, deltay, 255, subspecies);
  1606.             }   }
  1607.             break;
  1608. }   }   }
  1609.  
  1610. AGLOBAL void wormkillcreature(UBYTE player, UBYTE which)
  1611. {   /* if (which == 255)
  1612.     {   say("Attempted to kill invalid creature!", PURPLE);
  1613.         Delay(250);
  1614.         clearkybd();
  1615.         anykey(FALSE);
  1616.     }
  1617.     return; */
  1618.  
  1619.     if (creature[which].species == BANANA)
  1620.     {   if (creature[which].player == player)
  1621.         {   worm[player].lives += 2;
  1622.         } else
  1623.         {   worm[player].lives++;
  1624.         }
  1625.         stat(player, MINIHEALER);
  1626.     }
  1627.  
  1628.     if
  1629.     (   creature[which].species        == RAIN
  1630.      || (   creature[which].species    == FRAGMENT
  1631.          && creature[which].subspecies == BANANA
  1632.     )   )
  1633.     {   if (creature[which].player == player)
  1634.         {   wormscore(player, creature[which].score * 2);
  1635.         } else
  1636.         {   wormscore(player, creature[which].score);
  1637.     }   }
  1638.     else
  1639.     {   wormscore(player, creature[which].score);
  1640.     }
  1641.     creature[which].alive = FALSE;
  1642.  
  1643.     if (creature[which].species == FRAGMENT)
  1644.     {   if (creature[which].subspecies == BANANA)
  1645.         {   effect(FXGET_GROWER);
  1646.         } else
  1647.         {   assert(creature[which].subspecies == FRAGMENT);
  1648.             effect(FXUSE_ARMOUR);
  1649.     }   }
  1650.     elif (creature[which].species == RAIN)
  1651.     {   effect(FXGET_RAIN);
  1652. }   }
  1653.  
  1654. AGLOBAL void protcreature(UBYTE player, UBYTE which)
  1655. {   /* Handles collisions between protectors and creatures. */
  1656.  
  1657.     switch(creature[which].species)
  1658.     {
  1659.     case FRAGMENT:
  1660.         effect(FXBORN_PROTECTOR);
  1661.         if (creature[which].subspecies == BANANA)
  1662.         {   wormkillcreature(player, which);
  1663.         } else
  1664.         {   assert(creature[which].subspecies == FRAGMENT);
  1665.             reflect(which);
  1666.         }
  1667.     break;
  1668.     case MISSILE_C:
  1669.         if (player != creature[which].player)
  1670.         {   effect(FXBORN_PROTECTOR);
  1671.             wormkillcreature(player, which);
  1672.         } else creature[which].visible = FALSE;
  1673.     break;
  1674.     default:
  1675.         effect(FXBORN_PROTECTOR);
  1676.         wormkillcreature(player, which);
  1677.     break;
  1678. }   }
  1679.  
  1680. AGLOBAL void wormcreature(UBYTE player, UBYTE which)
  1681. {   SBYTE xx, yy;
  1682.  
  1683.     /* Handles collisions between worms and creatures. */
  1684.  
  1685.     if (creature[which].species == GIRAFFE)
  1686.     {   xx = worm[player].x - (worm[player].deltax * DISTANCE_GIRAFFE);
  1687.         yy = worm[player].y - (worm[player].deltay * DISTANCE_GIRAFFE);
  1688.  
  1689.         if
  1690.         (   valid(xx, yy)
  1691.          && !blockedsquare(xx, yy)
  1692.         )
  1693.         {   worm[player].deltax = -worm[player].deltax;
  1694.             worm[player].deltay = -worm[player].deltay;
  1695.             worm[player].x = xx;
  1696.             worm[player].y = yy;
  1697.  
  1698.             if (!worm[player].armour)
  1699.             {   worm[player].alive  = FALSE;
  1700.                 worm[player].cause  = GIRAFFE;
  1701.             }
  1702.  
  1703.             return;
  1704.     }   }
  1705.  
  1706.     if
  1707.     (   creature[which].species == DOG
  1708.      && creature[which].dormant == DORMANT
  1709.     )
  1710.     {   effect(FXBORN_DOG);
  1711.         creature[which].dormant = AWAKENING;
  1712.         creature[which].player  = player;
  1713.         worm[player].last       = DOG;
  1714.         return;
  1715.     }
  1716.  
  1717.     if
  1718.     (   creature[which].species == MISSILE_C
  1719.      && creature[which].player == player
  1720.     )
  1721.     {   creature[which].visible = FALSE;
  1722.         return;
  1723.     }
  1724.  
  1725.     if
  1726.     (   creature[which].species == FRAGMENT
  1727.      && creature[which].subspecies == FRAGMENT
  1728.      && worm[player].armour
  1729.     )
  1730.     {   effect(FXUSE_ARMOUR);
  1731.         if (creature[which].species == FRAGMENT)
  1732.         {   reflect(which);
  1733.         }
  1734.         return;
  1735.     }
  1736.  
  1737.     wormkillcreature(player, which);
  1738.  
  1739.     if (creature[which].species == RAIN)
  1740.     {   return;
  1741.      }
  1742.      if
  1743.     (   creature[which].species == FRAGMENT
  1744.      && creature[which].subspecies == BANANA
  1745.     )
  1746.     {   return;
  1747.     }
  1748.  
  1749.     if (worm[player].armour)
  1750.     {   effect(FXUSE_ARMOUR);
  1751.     } elif (creature[which].player != player)
  1752.     {   if (creature[which].species == MISSILE_C)
  1753.         {   worm[player].cause = FIRSTMISSILE + creature[which].player;
  1754.         } else
  1755.         {   worm[player].cause = creature[which].species;
  1756.         }
  1757.         worm[player].alive = FALSE;
  1758. }   }
  1759.  
  1760. MODULE void creaturecreature(UBYTE which1, UBYTE which2)
  1761. {   if
  1762.     (   creature[which1].species == MISSILE_C
  1763.      && creature[which2].species != MISSILE_C
  1764.     )
  1765.     {   wormkillcreature(creature[which1].player, which2);
  1766.     } elif
  1767.     (   creature[which1].species != MISSILE_C
  1768.      && creature[which2].species == MISSILE_C
  1769.     )
  1770.     {   wormkillcreature(creature[which2].player, which1);
  1771.     } else
  1772.     {   creature[which1].alive =
  1773.         creature[which2].alive = FALSE;
  1774.         change(creature[which1].x, creature[which1].y, BONUS);
  1775. }   }
  1776.  
  1777. MODULE void bounceoffcreature(UBYTE which, SBYTE x, SBYTE y)
  1778. {   if
  1779.     (   field[x][y] >= FIRSTCREATURE
  1780.      && creatureinfo[field[x][y] - FIRSTCREATURE].wall
  1781.     )
  1782.     {   creature[whichcreature(x, y, field[x][y], which)].alive = FALSE;
  1783.         change(x, y, BONUS);
  1784. }   }
  1785.  
  1786. MODULE ABOOL bouncecreature(UBYTE which, SBYTE x, SBYTE y)
  1787. {   if
  1788.     (    field[x][y] == METAL
  1789.      ||  field[x][y] == STONE
  1790.      ||  field[x][y] == WOOD
  1791.      || (field[x][y] >= FIRSTCREATURE && creatureinfo[field[x][y] - FIRSTCREATURE].wall)
  1792.      || (field[x][y] >= FIRSTTAIL && field[x][y] <= LASTTAIL)
  1793.      || (field[x][y] >= FIRSTGLOW && field[x][y] <= LASTGLOW)
  1794.     )
  1795.     {   return TRUE;
  1796.     } else
  1797.     {   return FALSE;
  1798. }   }
  1799.  
  1800. AGLOBAL UBYTE whichcreature(SBYTE x, SBYTE y, UBYTE species, UBYTE exception)
  1801. {   UBYTE i;
  1802.  
  1803.     for (i = 0; i <= CREATURES; i++)
  1804.     {   if
  1805.         (   creature[i].alive
  1806.          && creature[i].x       == x
  1807.          && creature[i].y       == y
  1808.          && creature[i].species == species
  1809.          && i                   != exception
  1810.         )
  1811.         {   return i;
  1812.     }   }
  1813.  
  1814. /*  say("Attempted to find invalid creature!", PURPLE);
  1815.     Delay(250);
  1816.     clearkybd();
  1817.     anykey(FALSE); */
  1818.  
  1819.     return 255; /* error code */
  1820. }
  1821.  
  1822. AGLOBAL void wormloop(SBYTE player)
  1823. {   SBYTE bestx = 0, besty = 0, // to avoid spurious warnings
  1824.           dirx, diry, i, j, x, y, index1, index2;
  1825.     SWORD bestgood, good;
  1826.     UBYTE c;
  1827.  
  1828.    /*  Amiga worm control
  1829.        Remove a keystroke from the worm queue
  1830.        Move worm (and add a keystroke to the dog queue)
  1831.        Check for enclosure
  1832.        Move protectors
  1833.        Collision detection
  1834.  
  1835.     AI: Amiga worm control.
  1836.  
  1837.     Worm checks ahead, left and right one square. Assigns opinions
  1838.     to those three choices and then takes the appropriate one.
  1839.  
  1840.     Things which slow the worm down are doubly feared; this is to avoid
  1841.     endless ramming situations. */
  1842.  
  1843.     if (worm[player].control == AMIGA)
  1844.     {   if (!arand(50))
  1845.             wormqueue(player, arand(2) - 1, arand(2) - 1);
  1846.         else
  1847.         {   bestgood = -128;
  1848.  
  1849.             for (i = 0; i <= 8; i++)
  1850.             {   switch(i % 3)
  1851.                 {
  1852.                 case 0:
  1853.                     dirx = -1;
  1854.                 break;
  1855.                 case 1:
  1856.                     dirx = 0;
  1857.                 break;
  1858.                 case 2:
  1859.                     dirx = 1;
  1860.                 break;
  1861.                 default:
  1862.                     assert(0);
  1863.                 break;
  1864.                 }
  1865.                 switch(i / 3)
  1866.                 {
  1867.                 case 0:
  1868.                     diry = -1;
  1869.                 break;
  1870.                 case 1:
  1871.                     diry = 0;
  1872.                 break;
  1873.                 case 2:
  1874.                     diry = 1;
  1875.                 break;
  1876.                 default:
  1877.                     assert(0);
  1878.                 break;
  1879.                 }
  1880.                 if
  1881.                 (   (   dirx == -worm[player].deltax
  1882.                      && diry == -worm[player].deltay
  1883.                     )
  1884.                  || (   dirx == 0
  1885.                      && diry == 0
  1886.                 )   )
  1887.                 {   continue;
  1888.                 }
  1889.  
  1890.                 c = field[xwrap(worm[player].x + dirx)][ywrap(worm[player].y + diry)];
  1891.                 if (c >= FIRSTNUMBER && c <= LASTNUMBER)
  1892.                     good = POINTS_LETTER;
  1893.                 elif (c >= FIRSTHEAD && c <= LASTHEAD)
  1894.                     good = -(PAIN_HEAD);
  1895.                 elif (c <= LASTOBJECT)
  1896.                     good = (SWORD) object[c].score;
  1897.                 elif (c == FIRSTPROTECTOR + player)
  1898.                     good = POINTS_EMPTY;
  1899.                 elif (c >= FIRSTGLOW && c <= LASTGLOW)
  1900.                 {   if (player == c - FIRSTGLOW)
  1901.                         good = -1;
  1902.                     else good = -(PAIN_GLOW);
  1903.                 } elif (c >= FIRSTGRAVE && c <= LASTGRAVE)
  1904.                 {   good = POINTS_GRAVE;
  1905.                 } elif (c >= FIRSTCHERRY && c <= LASTCHERRY)
  1906.                 {   good = POINTS_CHERRY; // should really be 2x if friendly
  1907.                 } elif (c >= FIRSTFLOWER && c <= LASTFLOWER)
  1908.                 {   good = POINTS_FLOWER; // should really be 2x if friendly
  1909.                 } elif (c >= FIRSTTAIL && c <= LASTTAIL)
  1910.                 {   if (worm[player].armour > 10)
  1911.                         if (player != c - FIRSTTAIL)
  1912.                             good = 2;
  1913.                         else good = 0;
  1914.                     elif (player == c - FIRSTTAIL)
  1915.                         good = -(PAIN_FRIENDLYTAIL);
  1916.                     else good = -(PAIN_ENEMYTAIL);
  1917.                 } else switch(c)
  1918.                 {
  1919.                 case GOLD:
  1920.                     good = POINTS_GOLD;
  1921.                 break;
  1922.                 case SILVER:
  1923.                     good = POINTS_SILVER;
  1924.                 break;
  1925.                 case EMPTY:
  1926.                     good = POINTS_EMPTY;
  1927.                 break;
  1928.                 case DYNAMITE:
  1929.                     good = 1;
  1930.                 break;
  1931.                 case SLIME:
  1932.                     if (worm[player].armour > 0)
  1933.                         good = 0;
  1934.                     else good = -(PAIN_SLIME);
  1935.                 break;
  1936.                 case WOOD:
  1937.                     good = -(PAIN_WOOD  * 3);
  1938.                 break;
  1939.                 case STONE:
  1940.                     good = -(PAIN_STONE * 3);
  1941.                 break;
  1942.                 case METAL:
  1943.                     good = -(PAIN_METAL * 3);
  1944.                 break;
  1945.                 case START:
  1946.                     good = POINTS_LETTER * 2;
  1947.                 break;
  1948.                 default:
  1949.                     if (c >= FIRSTCREATURE)
  1950.                     {   if (creature[whichcreature(xwrap(worm[player].x + dirx), ywrap(worm[player].y + diry), c, 255)].player == player)
  1951.                         {   good = creatureinfo[c - FIRSTCREATURE].score;
  1952.                         } elif (creatureinfo[c - FIRSTCREATURE].wall)
  1953.                         {   good = -(PAIN_CREATURE * 2);
  1954.                         } else good = -PAIN_CREATURE;
  1955.                     } else
  1956.                     {   // eg. frost, arrows
  1957.                         good = 0;
  1958.                     }
  1959.                 break;
  1960.                 }
  1961.                 if
  1962.                 (   good > bestgood
  1963.                  || (good == bestgood && dirx == worm[player].deltax && diry == worm[player].deltay)
  1964.                 )
  1965.                 {   bestx = dirx;
  1966.                     besty = diry;
  1967.                     bestgood = good;
  1968.             }   }
  1969.             if (bestgood < -2 && !arand(1))
  1970.             {   // turn in any of the 8 directions, or fire
  1971.                 wormqueue
  1972.                 (   player,
  1973.                     (SBYTE) ((arand(1) * 2) - 1),
  1974.                     (SBYTE) ((arand(1) * 2) - 1)
  1975.                 );
  1976.             }
  1977.             if (bestgood < 0 && !arand(2))
  1978.                 wormqueue(player, 0, 0);
  1979.             elif (bestx != worm[player].deltax || besty != worm[player].deltay)
  1980.                 wormqueue(player, bestx, besty);
  1981.     }   }
  1982.  
  1983.     /* remove a keystroke from the worm queue */
  1984.  
  1985.     if (worm[player].pos != -1)
  1986.     {   if (thewormqueue[player][0].deltax == 0 && thewormqueue[player][0].deltay == 0)
  1987.             wormbullet(player);
  1988.         else
  1989.         {   if (!worm[player].frosted)
  1990.             {   turnworm(player, thewormqueue[player][0].deltax, thewormqueue[player][0].deltay);
  1991.         }   }
  1992.         if (--worm[player].pos != -1)
  1993.         {   for (i = 0; i <= worm[player].pos; i++)
  1994.             {   thewormqueue[player][i].deltax = thewormqueue[player][i + 1].deltax;
  1995.                 thewormqueue[player][i].deltay = thewormqueue[player][i + 1].deltay;
  1996.     }   }   }
  1997.     worm[player].frosted = FALSE;
  1998.  
  1999.     /* move worm */
  2000.  
  2001.     if (!worm[player].speed)
  2002.     {    return;
  2003.     }
  2004.  
  2005.     if (worm[player].last == FIRSTTAIL + player)
  2006.     {    field[worm[player].x][worm[player].y] = FIRSTTAIL + player;
  2007.         index1 =       worm[player].olddeltax + 1 + (      (worm[player].olddeltay + 1) * 3);
  2008.         index2 = bsign(worm[player].deltax)   + 1 + ((bsign(worm[player].deltay)   + 1) * 3);
  2009.         drawtail(worm[player].x, worm[player].y, eachtail[player][0][index1][index2]);
  2010.     } elif (worm[player].last == FIRSTGLOW + player)
  2011.     {   field[worm[player].x][worm[player].y] = FIRSTGLOW + player;
  2012.         index1 =       worm[player].olddeltax + 1 + (      (worm[player].olddeltay + 1) * 3);
  2013.         index2 = bsign(worm[player].deltax)   + 1 + ((bsign(worm[player].deltay)   + 1) * 3);
  2014.         drawtail(worm[player].x, worm[player].y, eachtail[player][1][index1][index2]);
  2015.     } else
  2016.     {   change(worm[player].x, worm[player].y, worm[player].last);
  2017.     }
  2018.  
  2019.     worm[player].x = xwrap(worm[player].x + worm[player].deltax);
  2020.     worm[player].y = ywrap(worm[player].y + worm[player].deltay);
  2021.  
  2022.     if (worm[player].glow)
  2023.     {   worm[player].last = FIRSTGLOW + player;
  2024.     } else
  2025.     {   worm[player].last = FIRSTTAIL + player;
  2026.     }
  2027.  
  2028.     for (i = 0; i <= CREATURES; i++)
  2029.     {   if
  2030.         (   creature[i].alive
  2031.          && creature[i].species == DOG
  2032.          && creature[i].dormant >  DORMANT
  2033.          && creature[i].player  == player
  2034.         )
  2035.         {   if (!worm[player].rammed)
  2036.                 dogqueue(i, worm[player].deltax, worm[player].deltay);
  2037.             if (creature[i].dormant < CHASING)
  2038.             {   creature[i].dormant++;
  2039.                 drawcreature(i);
  2040.     }   }   }
  2041.  
  2042.     /* The deltas are not changed back to the range of -1..1 until after
  2043.     the dogs have looked at the queue. This enables them to jump properly. */
  2044.  
  2045.     worm[player].rammed = FALSE;
  2046.     worm[player].deltax = bsign(worm[player].deltax);
  2047.     worm[player].deltay = bsign(worm[player].deltay);
  2048.     worm[player].olddeltax = worm[player].deltax;
  2049.     worm[player].olddeltay = worm[player].deltay;
  2050.  
  2051.     /*  check for enclosure
  2052.         #####
  2053.         #...#
  2054.         #...# . = interior
  2055.         #...# # = tail
  2056.         ####! ! = head */
  2057.  
  2058.     enclosed = FALSE;
  2059.     for (i = ENCLOSURE_MIN; i <= ENCLOSURE_MAX; i++) // for each size of interior
  2060.     {   for (j = 0; j <= 3; j++) // four times, once for each direction
  2061.         {   checkrectangle(j, player, i, i);
  2062.             if (worm[player].encloser)
  2063.             {   checkrectangle(j, player, i, i + 1);
  2064.                 checkrectangle(j, player, i + 1, i);
  2065.     }   }   }
  2066.  
  2067.     protectorloop1(player);
  2068.  
  2069.     // head collision detection
  2070.     wormcol(player, worm[player].x, worm[player].y);
  2071.     // draw head
  2072.     field[worm[player].x][worm[player].y] = FIRSTHEAD + player;
  2073.     drawhead(player);
  2074.  
  2075.     updatearrow(worm[player].arrowy);
  2076.     worm[player].arrowy = worm[player].y;
  2077.     updatearrow(worm[player].arrowy);
  2078.  
  2079.     protectorloop2(player);
  2080.  
  2081.     if (worm[player].cutter)
  2082.     {   // straight ahead
  2083.         x = xwrap(worm[player].x + worm[player].deltax);
  2084.         y = ywrap(worm[player].y + worm[player].deltay);
  2085.         squareblast(HEAD, player, field[x][y], x, y, TRUE, FALSE);
  2086.         // left
  2087.         if (!worm[player].deltax || !worm[player].deltay)
  2088.         {   // if orthagonal
  2089.             x = xwrap(worm[player].x + worm[player].deltay);
  2090.             y = ywrap(worm[player].y - worm[player].deltax);
  2091.         } else // diagonal
  2092.         {   if (worm[player].deltax == worm[player].deltay)
  2093.             {   x = xwrap(worm[player].x + worm[player].deltax);
  2094.                 y = ywrap(worm[player].y - worm[player].deltay);
  2095.             } else
  2096.             {   x = xwrap(worm[player].x - worm[player].deltax);
  2097.                 y = ywrap(worm[player].y + worm[player].deltay);
  2098.         }   }
  2099.         squareblast(HEAD, player, field[x][y], x, y, TRUE, FALSE);
  2100.         // right
  2101.         if (!worm[player].deltax || !worm[player].deltay)
  2102.         {   // if orthagonal
  2103.             x = xwrap(worm[player].x - worm[player].deltay);
  2104.             y = ywrap(worm[player].y + worm[player].deltax);
  2105.         } else // diagonal
  2106.         {   if (worm[player].deltax == worm[player].deltay)
  2107.             {   x = xwrap(worm[player].x - worm[player].deltax);
  2108.                 y = ywrap(worm[player].y + worm[player].deltay);
  2109.             } else
  2110.             {   x = xwrap(worm[player].x + worm[player].deltax);
  2111.                 y = ywrap(worm[player].y - worm[player].deltay);
  2112.         }   }
  2113.         squareblast(HEAD, player, field[x][y], x, y, TRUE, FALSE);
  2114.         // ahead left
  2115.         if (!worm[player].deltax || !worm[player].deltay)
  2116.         {   // if orthagonal
  2117.             if (worm[player].deltax) // if east or west
  2118.             {   x = xwrap(worm[player].x + worm[player].deltax);
  2119.                 y = ywrap(worm[player].y - worm[player].deltax);
  2120.             } else // north or south
  2121.             {   x = xwrap(worm[player].x + worm[player].deltay);
  2122.                 y = ywrap(worm[player].y + worm[player].deltay);
  2123.         }   }
  2124.         else // diagonal
  2125.         {   if (worm[player].deltax == worm[player].deltay)
  2126.             {   x = xwrap(worm[player].x + worm[player].deltax);
  2127.                 y = worm[player].y;
  2128.             } else
  2129.             {   x = worm[player].x;
  2130.                 y = ywrap(worm[player].y + worm[player].deltay);
  2131.         }   }
  2132.         squareblast(HEAD, player, field[x][y], x, y, TRUE, FALSE);
  2133.         // ahead right
  2134.         if (!worm[player].deltax || !worm[player].deltay)
  2135.         {   // if orthagonal
  2136.             if (worm[player].deltax) // if east or west
  2137.             {   x = xwrap(worm[player].x + worm[player].deltax);;
  2138.                 y = ywrap(worm[player].y + worm[player].deltax);
  2139.             } else // north or south
  2140.             {   x = xwrap(worm[player].x - worm[player].deltay);
  2141.                 y = ywrap(worm[player].y + worm[player].deltay);
  2142.         }   }
  2143.         else // diagonal
  2144.         {   if (worm[player].deltax == worm[player].deltay)
  2145.             {   x = worm[player].x;
  2146.                 y = ywrap(worm[player].y + worm[player].deltay);
  2147.             } else
  2148.             {   x = xwrap(worm[player].x + worm[player].deltax);
  2149.                 y = worm[player].y;
  2150.         }   }
  2151.         squareblast(HEAD, player, field[x][y], x, y, TRUE, FALSE);
  2152. }   }
  2153.  
  2154. MODULE void protcol(SBYTE player, SBYTE x, SBYTE y, SBYTE thisprot)
  2155. {   UBYTE c = field[x][y];
  2156.     SBYTE i;
  2157.  
  2158.     if (c == EMPTY)
  2159.     {   ;
  2160.     } elif (c >= FIRSTHEAD && c <= LASTHEAD)
  2161.     {   protworm(x, y, player, c - FIRSTHEAD);
  2162.     } elif (c >= FIRSTPROTECTOR && c <= LASTPROTECTOR)
  2163.     {   protprot(x, y, player, c - FIRSTPROTECTOR);
  2164.     } elif (c >= FIRSTTAIL && c <= LASTTAIL)
  2165.     {   if (player == c - FIRSTTAIL)
  2166.         {   protector[player][thisprot].visible = FALSE;
  2167.     }   }
  2168.     elif
  2169.     (   c == STONE
  2170.      || c == WOOD
  2171.      || c == METAL
  2172.      || c == TELEPORT
  2173.      || c == FIRSTGLOW + player
  2174.      || c == START
  2175.     )
  2176.     {   protector[player][thisprot].visible = FALSE;
  2177.     } elif (c >= FIRSTCREATURE)
  2178.     {   i = whichcreature(x, y, c, 255);
  2179.         protcreature(player, i);
  2180.     } else
  2181.     {   bothcol(player, x, y);
  2182. }   }
  2183.  
  2184. AGLOBAL void bothcol(SBYTE player, SBYTE x, SBYTE y)
  2185. {   UBYTE c = field[x][y], i;
  2186.  
  2187.     if (c >= FIRSTNUMBER && c <= LASTNUMBER)
  2188.     {   if (!(getnumber(player)))
  2189.         {   putnumber();
  2190.     }   }
  2191.     elif (c >= FIRSTFLOWER && c <= LASTFLOWER)
  2192.     {   effect(FXDING);
  2193.         if (player == c - FIRSTFLOWER)
  2194.         {   wormscore(player, POINTS_FLOWER * 2);
  2195.             worm[player].lives += 2;
  2196.         } else
  2197.         {   wormscore(player, POINTS_FLOWER);
  2198.             worm[player].lives++;
  2199.         }
  2200.         stat(player, MINIHEALER);
  2201.  
  2202.         if (level != 0)
  2203.         {   getnumber(player);
  2204.             change(numberx, numbery, FIRSTNUMBER + number - 1);
  2205.             updatearrow(numbery);
  2206.     }   }
  2207.     elif (c >= FIRSTCHERRY && c <= LASTCHERRY)
  2208.     {   effect(FXDING);
  2209.         if (player == c - FIRSTCHERRY)
  2210.         {   wormscore(player, POINTS_CHERRY * 2);
  2211.         } else
  2212.         {   wormscore(player, POINTS_CHERRY);
  2213.     }   }
  2214.     elif (c <= LASTOBJECT)
  2215.     {   wormscore(player, wormobject(player, x, y));
  2216.     } elif (c >= FIRSTGRAVE && c <= LASTGRAVE)
  2217.     {   effect(FXGET_GRAVE);
  2218.         wormscore(player, POINTS_GRAVE);
  2219.  
  2220.         worm[player].multi *= worm[c - FIRSTGRAVE].multi;
  2221.         if (worm[player].multi > 1)
  2222.         {   if (worm[player].multi > MULTILIMIT)
  2223.                 worm[player].multi = MULTILIMIT;
  2224.         }
  2225.         worm[player].power += worm[c - FIRSTGRAVE].power;
  2226.         if (worm[player].power > 1)
  2227.         {   if (worm[player].power > POWERLIMIT)
  2228.                 worm[player].power = POWERLIMIT;
  2229.             stat(player, POWER);
  2230.             worm[c - FIRSTGRAVE].power = 0;
  2231.             stat(c - FIRSTGRAVE, POWER);
  2232.         }
  2233.         worm[player].ammo += worm[c - FIRSTGRAVE].ammo;
  2234.         if (worm[player].ammo > 0)
  2235.         {   if (worm[player].ammo > AMMOLIMIT)
  2236.                 worm[player].ammo = AMMOLIMIT;
  2237.             stat(player, AMMO);
  2238.             worm[c - FIRSTGRAVE].ammo = 0;
  2239.             stat(c - FIRSTGRAVE, AMMO);
  2240.         }
  2241.         if (worm[c - FIRSTGRAVE].brakes)
  2242.         {   worm[player].brakes = TRUE;
  2243.             stat(player, BRAKES);
  2244.             worm[c - FIRSTGRAVE].brakes = FALSE;
  2245.             worm[c - FIRSTGRAVE].speed = NORMAL;
  2246.             stat(c - FIRSTGRAVE, BRAKES);
  2247.         }
  2248.         if (worm[c - FIRSTGRAVE].affixer)
  2249.         {   worm[player].affixer = TRUE;
  2250.             worm[c - FIRSTGRAVE].affixer = FALSE;
  2251.         }
  2252.         if (worm[c - FIRSTGRAVE].remnants)
  2253.         {   worm[player].remnants = TRUE;
  2254.             worm[c - FIRSTGRAVE].remnants = FALSE;
  2255.         }
  2256.         if (worm[c - FIRSTGRAVE].sideshot)
  2257.         {   worm[player].sideshot = TRUE;
  2258.             worm[c - FIRSTGRAVE].sideshot = FALSE;
  2259.         }
  2260.         if (worm[c - FIRSTGRAVE].pusher)
  2261.         {   worm[player].pusher = TRUE;
  2262.             worm[c - FIRSTGRAVE].pusher = FALSE;
  2263.         }
  2264.         if (worm[c - FIRSTGRAVE].encloser)
  2265.         {   worm[player].encloser = TRUE;
  2266.             worm[c - FIRSTGRAVE].encloser = FALSE;
  2267.         }
  2268.         if (worm[c - FIRSTGRAVE].autojump)
  2269.         {   worm[player].autojump = TRUE;
  2270.             worm[c - FIRSTGRAVE].autojump = FALSE;
  2271.         }
  2272.  
  2273.         if (worm[c - FIRSTGRAVE].armour)
  2274.         {   worm[player].armour += worm[c - FIRSTGRAVE].armour;
  2275.             if (worm[player].armour > ARMOURLIMIT)
  2276.                 worm[player].armour = ARMOURLIMIT;
  2277.             worm[c - FIRSTGRAVE].armour = 0;
  2278.         }
  2279.         if (worm[c - FIRSTGRAVE].glow)
  2280.         {   worm[player].glow += worm[c - FIRSTGRAVE].glow;
  2281.             if (worm[player].glow > GLOWLIMIT)
  2282.                 worm[player].glow = GLOWLIMIT;
  2283.             worm[c - FIRSTGRAVE].glow = 0;
  2284.         }
  2285.         if (worm[c - FIRSTGRAVE].cutter)
  2286.         {   worm[player].cutter += worm[c - FIRSTGRAVE].cutter;
  2287.             if (worm[player].armour > CUTTERLIMIT)
  2288.                 worm[player].armour = CUTTERLIMIT;
  2289.             worm[c - FIRSTGRAVE].cutter = 0;
  2290.         }
  2291.  
  2292.         for (i = 0; i <= LASTOBJECT; i++)
  2293.         {   icon(player, i);
  2294.             icon(c - FIRSTGRAVE, i);
  2295.     }   }
  2296.     else
  2297.     {   switch(c)
  2298.         {
  2299.         case SILVER:
  2300.             wormscore(player, POINTS_SILVER);
  2301.         break;
  2302.         case GOLD:
  2303.             wormscore(player, POINTS_GOLD);
  2304.         break;
  2305.         case DYNAMITE:
  2306.             effect(FXUSE_BOMB);
  2307.             banging = TRUE;
  2308.             bangdynamite(x, y, player);
  2309.         break;
  2310.         default:
  2311.         break;
  2312. }   }   }
  2313.  
  2314. MODULE void wormbullet(SBYTE player)
  2315. {   ABOOL finished,
  2316.           numbered = FALSE;
  2317.     FLAG  final;
  2318.     SBYTE distance,
  2319.           i, j,
  2320.           x, y;
  2321.     UBYTE c;
  2322.  
  2323.     if (!worm[player].ammo)
  2324.     {   stat(player, BONUS); // why?
  2325.         if (worm[player].speed == FAST)
  2326.             distance = DISTANCE_FAST;
  2327.         elif (worm[player].speed == NORMAL)
  2328.             distance = DISTANCE_NORMAL;
  2329.         else
  2330.         {   distance = DISTANCE_SLOW;
  2331.         }
  2332.  
  2333.         assert(abs(worm[player].deltax) <= 1 && abs(worm[player].deltay) <= 1);
  2334.         x = xwrap(worm[player].x + (worm[player].deltax * distance));
  2335.         y = ywrap(worm[player].y + (worm[player].deltay * distance));
  2336.         c = field[x][y];
  2337.  
  2338.         if
  2339.         (   (c < FIRSTGLOW || c > LASTGLOW || player != c - FIRSTGLOW)
  2340.          && (!blockedsquare(x, y))
  2341.         )
  2342.         {   worm[player].deltax = worm[player].deltax * distance;
  2343.             worm[player].deltay = worm[player].deltay * distance;
  2344.             // the *= operator seems not to work correctly under StormC
  2345.     }   }
  2346.     else
  2347.     {   effect(FXUSE_AMMO);
  2348.         worm[player].ammo--;
  2349.         stat(player, AMMO);
  2350.         if (worm[player].sideshot)
  2351.         {   bullet[7].alive      = bullet[8].alive      = TRUE;
  2352.             bullet[7].teleported = bullet[8].teleported = 0;
  2353.             bullet[7].visible    = bullet[8].visible    = TRUE;
  2354.             bullet[7].reflected  = bullet[8].reflected  = FALSE;
  2355.             if (!worm[player].deltax && worm[player].deltay)
  2356.             {   bullet[7].deltax = -1;
  2357.                 bullet[8].deltax = 1;
  2358.                 bullet[7].deltay = bullet[8].deltay = 0;
  2359.             } elif (worm[player].deltax && !worm[player].deltay)
  2360.             {   bullet[7].deltax = bullet[8].deltax = 0;
  2361.                 bullet[7].deltay = -1;
  2362.                 bullet[8].deltay = 1;
  2363.             } else /* worm is diagonal */
  2364.             {   if (worm[player].deltax == worm[player].deltay)
  2365.                 {   bullet[7].deltax = 1;
  2366.                     bullet[7].deltay = -1;
  2367.                 } else
  2368.                 {   bullet[7].deltax = -1;
  2369.                     bullet[7].deltay = -1;
  2370.                 }
  2371.                 bullet[8].deltax = -bullet[7].deltax;
  2372.                 bullet[8].deltay = -bullet[7].deltay;
  2373.             }
  2374.             bullet[7].x = worm[player].x + bullet[7].deltax;
  2375.             bullet[7].y = worm[player].y + bullet[7].deltay;
  2376.             bullet[8].x = worm[player].x + bullet[8].deltax;
  2377.             bullet[8].y = worm[player].y + bullet[8].deltay;
  2378.         }
  2379.  
  2380.         for (i = 0; i <= worm[player].power; i++)
  2381.         {   bullet[i].alive      = TRUE;
  2382.             bullet[i].teleported = 0;
  2383.             bullet[i].visible    = TRUE;
  2384.             bullet[i].reflected  = FALSE;
  2385.             bullet[i].deltax     = worm[player].deltax;
  2386.             bullet[i].deltay     = worm[player].deltay;
  2387.             if (i % 2 == 0)
  2388.                 distance = i / 2;
  2389.             else distance = -((i + 1) / 2);
  2390.             if (worm[player].deltax == 0)
  2391.             {   bullet[i].x = worm[player].x + distance;
  2392.                 bullet[i].y = worm[player].y + worm[player].deltay;
  2393.             } elif (worm[player].deltay == 0)
  2394.             {   bullet[i].x = worm[player].x + worm[player].deltax;
  2395.                 bullet[i].y = worm[player].y + distance;
  2396.             } else
  2397.             {   switch (i)
  2398.                 {
  2399.                 case 0:
  2400.                     bullet[i].x = worm[player].x + worm[player].deltax;
  2401.                     bullet[i].y = worm[player].y + worm[player].deltay;
  2402.                 break;
  2403.                 case 1:
  2404.                     bullet[i].x = worm[player].x + worm[player].deltax;
  2405.                     bullet[i].y = worm[player].y;
  2406.                 break;
  2407.                 case 2:
  2408.                     bullet[i].x = worm[player].x;
  2409.                     bullet[i].y = worm[player].y + worm[player].deltay;
  2410.                 break;
  2411.                 case 3:
  2412.                     bullet[i].x = worm[player].x + worm[player].deltax * 2;
  2413.                     bullet[i].y = worm[player].y;
  2414.                 break;
  2415.                 case 4:
  2416.                     bullet[i].x = worm[player].x;
  2417.                     bullet[i].y = worm[player].y + worm[player].deltay * 2;
  2418.                 break;
  2419.                 case 5:
  2420.                     bullet[i].x = worm[player].x + worm[player].deltax * 2;
  2421.                     bullet[i].y = worm[player].y - worm[player].deltay;
  2422.                 break;
  2423.                 case 6:
  2424.                     bullet[i].x = worm[player].x - worm[player].deltax;
  2425.                     bullet[i].y = worm[player].y + worm[player].deltay * 2;
  2426.                 break;
  2427.                 default:
  2428.                 break;
  2429.         }   }   }
  2430.  
  2431.         for (i = 0; i <= 8; i++)
  2432.         {   if (bullet[i].alive && (!valid(bullet[i].x, bullet[i].y)))
  2433.             {    bullet[i].alive = FALSE;
  2434.         }   }
  2435.  
  2436.         /* Bullets are now set up. */
  2437.  
  2438.         finished = FALSE;
  2439.         while (!finished)
  2440.         {   finished = TRUE;
  2441.             for (i = 0; i <= 8; i++)
  2442.             {   if (bullet[i].alive)
  2443.                 {   if (bullet[i].visible)
  2444.                     {   if (worm[player].remnants)
  2445.                             change(bullet[i].x, bullet[i].y, FIRSTGLOW + player);
  2446.                         else change(bullet[i].x, bullet[i].y, EMPTY);
  2447.                     }
  2448.  
  2449.                     finished = FALSE;
  2450.                     bullet[i].visible = TRUE;
  2451.                     if (bullet[i].reflected)
  2452.                     {   bullet[i].x -= bullet[i].deltax;
  2453.                         bullet[i].y -= bullet[i].deltay;
  2454.                     } else
  2455.                     {   bullet[i].x += bullet[i].deltax;
  2456.                         bullet[i].y += bullet[i].deltay;
  2457.                     }
  2458.                     x = bullet[i].x;
  2459.                     y = bullet[i].y;
  2460.                     c = field[x][y];
  2461.                     if (!(valid(x, y)))
  2462.                         bullet[i].alive = FALSE;
  2463.                     elif (x == worm[player].x && y == worm[player].y)
  2464.                     {   /* hit by own bullet */
  2465.                         bullet[i].alive = FALSE;
  2466.                         if (worm[player].armour == 0)
  2467.                         {   worm[player].cause = FIRSTFIRE + player;
  2468.                             worm[player].alive = FALSE;
  2469.                     }   }
  2470.                     elif (c >= FIRSTHEAD && c <= LASTHEAD)
  2471.                     {   if (worm[c - FIRSTHEAD].armour == 0)
  2472.                         {   worm[c - FIRSTHEAD].cause = FIRSTFIRE + player;
  2473.                             worm[c - FIRSTHEAD].alive = FALSE;
  2474.                         } else effect(FXUSE_ARMOUR);
  2475.                         bullet[i].alive = FALSE;
  2476.                     } elif (c >= FIRSTPROTECTOR && c <= LASTPROTECTOR)
  2477.                     {   if (player != c - FIRSTPROTECTOR)
  2478.                         {   effect(FXBORN_PROTECTOR);
  2479.                             bullet[i].alive = FALSE;
  2480.                         } else bullet[i].visible = FALSE;
  2481.                     } elif (c >= FIRSTNUMBER && c <= LASTNUMBER)
  2482.                     {   final = getnumber(player);
  2483.                         numbered = TRUE;
  2484.                     } elif (c >= FIRSTGRAVE && c <= LASTGRAVE)
  2485.                     {   bullet[i].alive = FALSE;
  2486.                     } else
  2487.                     {   switch(c)
  2488.                         {
  2489.                         case MINIBOMB:
  2490.                             // sets it off, for your benefit
  2491.                             bullet[i].alive = FALSE;
  2492.                             bombblast(HEAD, player, x, y, FALSE);
  2493.                         break;
  2494.                         case SUPERBOMB:
  2495.                             // sets it off, for your benefit
  2496.                             bullet[i].alive = FALSE;
  2497.                             bombblast(HEAD, player, x, y, TRUE);
  2498.                         break;
  2499.                         case SLIME:
  2500.                         case WOOD:
  2501.                             // destroys one layer of it
  2502.                             bullet[i].alive = FALSE;
  2503.                             change(x, y, EMPTY);
  2504.                         break;
  2505.                         case METAL:
  2506.                             if (bullet[i].reflected)
  2507.                                 bullet[i].alive = FALSE;
  2508.                             else
  2509.                             {   bullet[i].reflected = TRUE;
  2510.                                 bullet[i].x -= bullet[i].deltax * 2;
  2511.                                 bullet[i].y -= bullet[i].deltay * 2;
  2512.                             }
  2513.                             break;
  2514.                         case STONE:
  2515.                         case START:
  2516.                             bullet[i].alive = FALSE;
  2517.                         break;
  2518.                         case TELEPORT:
  2519.                             j = whichteleport(bullet[i].x, bullet[i].y);
  2520.                             if (bullet[i].teleported == 2 || blockedtel(j, bullet[i].deltax, bullet[i].deltay))
  2521.                             {   bullet[i].alive = FALSE;
  2522.                             } else
  2523.                             {   effect(FXUSE_TELEPORT);
  2524.                                 bullet[i].visible = FALSE;
  2525.                                 bullet[i].teleported++;
  2526.                                 bullet[i].x = teleport[partner(j)].x;
  2527.                                 bullet[i].y = teleport[partner(j)].y;
  2528.                             }
  2529.                         break;
  2530.                         default:
  2531.                             if (c >= FIRSTCREATURE)
  2532.                             {   j = whichcreature(x, y, c, 255);
  2533.                                 bullet[i].alive = FALSE;
  2534.                                 wormkillcreature(player, j);
  2535.                                 change(x, y, FIRSTFLOWER + player);
  2536.                             } elif (c <= LASTOBJECT)
  2537.                             {   bullet[i].alive = FALSE;
  2538.                                 change(x, y, FIRSTCHERRY + player);
  2539.                             }
  2540.                         break;
  2541.                     }   }
  2542.  
  2543.                     // x and y need this refreshing here
  2544.                     x = bullet[i].x;
  2545.                     y = bullet[i].y;
  2546.                     if (bullet[i].alive && bullet[i].visible)
  2547.                     {   draw(x, y, FIRSTFIRE + player);
  2548.         }   }   }   }
  2549.         if (numbered && !final)
  2550.         {   putnumber();
  2551.         }
  2552.         clearkybd();
  2553. }   }
  2554.  
  2555. MODULE void dogqueue(SBYTE which, SBYTE deltax, SBYTE deltay)
  2556. {   if (creature[which].pos < DOGQUEUELIMIT)
  2557.     {   creature[which].pos++;
  2558.         thedogqueue[which][creature[which].pos].deltax = deltax;
  2559.         thedogqueue[which][creature[which].pos].deltay = deltay;
  2560.     } else
  2561.     {   creature[which].alive = FALSE;
  2562.         change(creature[which].x, creature[which].y, EMPTY);
  2563. }   }
  2564.  
  2565. /* NAME     queue -- adds a keystroke to the key queue
  2566. SYNOPSIS    name(SBYTE, SBYTE, SBYTE);
  2567. FUNCTION    Adds a keystroke to the in-game key queue.
  2568. INPUTS      player - player that pressed the key
  2569.             deltax - the deltax of the key
  2570.             deltay - the deltay of the key
  2571. IMPLEMENTATION
  2572.             thewormqueue[] array has WORMQUEUELIMIT as its last index.
  2573.             It is implemented as a FIFO stack rather than LIFO so that
  2574.             the keystrokes are processed in the correct order (that is,
  2575.             the order in which they were pressed). The oldest keystroke
  2576.             is always at index [0], the next oldest at [1], and so on
  2577.             upwards to the newest keystroke, at [worm[player].pos].
  2578.             Keystrokes are removed from the bottom of the array ([0]),
  2579.             and the rest of the array is shuffled down to fill the gap,
  2580.             so that the contents of [1] go to [0], the contents of [2]
  2581.             go to [1], etc. worm[player].pos is adjusted to always point
  2582.             to the newest entry, which is the 'end' of the queue.
  2583. MODULE      engine2.c */
  2584.  
  2585. AGLOBAL void wormqueue(SBYTE player, SBYTE deltax, SBYTE deltay)
  2586. {   if (worm[player].pos < WORMQUEUELIMIT)
  2587.     {   worm[player].pos++;
  2588.         thewormqueue[player][worm[player].pos].deltax = deltax;
  2589.         thewormqueue[player][worm[player].pos].deltay = deltay;
  2590. }   }
  2591.  
  2592. AGLOBAL void drawcreature(UBYTE which)
  2593. {   switch(creature[which].species)
  2594.     {
  2595.     case BIRD:
  2596.         draw(creature[which].x, creature[which].y, birdframes[creature[which].frame]);
  2597.     break;
  2598.     case BULL:
  2599.         if (creature[which].dir == -1)
  2600.         {   draw(creature[which].x, creature[which].y, BULLLEFT);
  2601.         } else
  2602.         {   assert(creature[which].dir == 1);
  2603.             draw(creature[which].x, creature[which].y, BULLRIGHT);
  2604.         }
  2605.     break;
  2606.     case RABBIT:
  2607.         if (creature[which].deltax == -1)
  2608.         {   draw(creature[which].x, creature[which].y, RABBITLEFT);
  2609.         } else
  2610.         {   assert(creature[which].deltax == 1);
  2611.             draw(creature[which].x, creature[which].y, RABBITRIGHT);
  2612.         }
  2613.     break;
  2614.     case DOG:
  2615.         if (creature[which].dormant == 0)
  2616.         {   draw(creature[which].x, creature[which].y, DOGDORMANT);
  2617.         } elif (creature[which].dormant < CHASING)
  2618.         {   draw(creature[which].x, creature[which].y, DOGAWAKENING);
  2619.         } else
  2620.         {   draw(creature[which].x, creature[which].y, DOGCHASING);
  2621.         }
  2622.     break;
  2623.     case RAIN:
  2624.         draw(creature[which].x, creature[which].y, FIRSTRAIN + creature[which].player);
  2625.     break;
  2626.     case FRAGMENT:
  2627.         if (creature[which].subspecies == FRAGMENT)
  2628.         {   draw(creature[which].x, creature[which].y, FRAGMENT);
  2629.         } else
  2630.         {   assert(creature[which].subspecies == BANANA);
  2631.             draw(creature[which].x, creature[which].y, bananaframes[creature[which].player][creature[which].frame]);
  2632.         }
  2633.     break;
  2634.     case FROG:
  2635.         if (creature[which].dir == -1)
  2636.         {   draw(creature[which].x, creature[which].y, FROGLEFT);
  2637.         } else
  2638.         {   assert(creature[which].dir == 1);
  2639.             draw(creature[which].x, creature[which].y, FROGRIGHT);
  2640.         }
  2641.     break;
  2642.     case MISSILE_C:
  2643.         draw(creature[which].x, creature[which].y, missileframes[creature[which].player][creature[which].frame]);
  2644.     break;
  2645.     default:
  2646.         draw(creature[which].x, creature[which].y, creature[which].species);
  2647.     break;
  2648.     }
  2649.  
  2650.     field[creature[which].x][creature[which].y] = creature[which].species;
  2651. }
  2652.  
  2653. AGLOBAL ABOOL blockedsquare(SBYTE x, SBYTE y)
  2654. {   UBYTE c = field[x][y];
  2655.  
  2656.     if
  2657.     (   c == STONE
  2658.      || c == METAL
  2659.      || c == WOOD
  2660.      || (c >= FIRSTCREATURE && creatureinfo[c - FIRSTCREATURE].wall)
  2661.     )
  2662.     {   return TRUE;
  2663.     } else
  2664.     {   return FALSE;
  2665. }   }
  2666.  
  2667. MODULE void choosediagonal(UBYTE which)
  2668. {   SBYTE number;
  2669.  
  2670.     /* This routine is a workaround for a very strange bug. */
  2671.  
  2672.     do
  2673.     {   number = arand(3);
  2674.         switch(number)
  2675.         {
  2676.         case 0:
  2677.             creature[which].deltax = -1;
  2678.             creature[which].deltay = -1;
  2679.         break;
  2680.         case 1:
  2681.             creature[which].deltax = -1;
  2682.             creature[which].deltay =  1;
  2683.         break;
  2684.         case 2:
  2685.             creature[which].deltax =  1;
  2686.             creature[which].deltay = -1;
  2687.         break;
  2688.         case 3:
  2689.             creature[which].deltax =  1;
  2690.             creature[which].deltay =  1;
  2691.         break;
  2692.         default:
  2693.             assert(0);
  2694.         break;
  2695.         } // end switch
  2696.     } while (!valid(creature[which].x + creature[which].deltax, creature[which].y + creature[which].deltay));
  2697. }
  2698.  
  2699. MODULE void chooseorthagonal(SBYTE* xx, SBYTE* yy)
  2700. {   SBYTE number;
  2701.  
  2702.     /* This routine is a workaround for a very strange bug. */
  2703.  
  2704.     number = arand(3);
  2705.     switch(number)
  2706.     {
  2707.     case 0:
  2708.         *xx =  0;
  2709.         *yy = -1;
  2710.     break;
  2711.     case 1:
  2712.         *xx =  0;
  2713.         *yy =  1;
  2714.     break;
  2715.     case 2:
  2716.         *xx = -1;
  2717.         *yy =  0;
  2718.     break;
  2719.     case 3:
  2720.         *xx =  1;
  2721.         *yy =  0;
  2722.     break;
  2723.     default:
  2724.         assert(0);
  2725.     break;
  2726. }   }
  2727.  
  2728. AGLOBAL void stoppedwormloop(SBYTE player)
  2729. {    SBYTE i;
  2730.     FLAG go = FALSE;
  2731.  
  2732.     /* remove a keystroke from the worm queue
  2733.     The worm still has deltax and deltay whilst stopped. */
  2734.  
  2735.     if (!(r % SPEED_PROTECTOR))
  2736.     {    protectorloop1(player);
  2737.         protectorloop2(player);
  2738.     } // affixer becomes a disadvantage in this situation
  2739.  
  2740.     if (worm[player].pos != -1)
  2741.     {   if (thewormqueue[player][0].deltax == 0 && thewormqueue[player][0].deltay == 0)
  2742.         {   if (worm[player].ammo)
  2743.             {    wormbullet(player); // you can fire bullets whilst stopped :-)
  2744.         }    }
  2745.         elif
  2746.         (    thewormqueue[player][0].deltax != -worm[player].deltax
  2747.          || thewormqueue[player][0].deltay != -worm[player].deltay
  2748.         )
  2749.         {    worm[player].speed = SLOW;
  2750.             stat(player, BRAKES);
  2751.             worm[player].deltax = thewormqueue[player][0].deltax;
  2752.             worm[player].deltay = thewormqueue[player][0].deltay;
  2753.             worm[player].frosted = FALSE;
  2754.             go = TRUE;
  2755.         }
  2756.         if (--worm[player].pos != -1)
  2757.         {   for (i = 0; i <= worm[player].pos; i++)
  2758.             {   thewormqueue[player][i].deltax = thewormqueue[player][i + 1].deltax;
  2759.                 thewormqueue[player][i].deltay = thewormqueue[player][i + 1].deltay;
  2760.          }   }
  2761.         if (go)
  2762.         {    wormloop(player);
  2763.             worm[player].wait = TRUE;
  2764. }    }    }
  2765.  
  2766. MODULE void protectorloop1(SBYTE player)
  2767. {    SBYTE i;
  2768.  
  2769.     // move protectors
  2770.  
  2771.     for (i = 0; i <= PROTECTORS; i++)
  2772.     {   if (protector[player][i].alive)
  2773.         {   if (protector[player][i].visible)
  2774.             {   change(protector[player][i].x, protector[player][i].y, protector[player][i].last);
  2775.             } else protector[player][i].visible = TRUE;
  2776.             protector[player][i].last = EMPTY;
  2777.             if (i == NOSE)
  2778.             {   protector[player][i].relx = worm[player].deltax * DISTANCE_NOSE;
  2779.                 protector[player][i].rely = worm[player].deltay * DISTANCE_NOSE;
  2780.                 if (!worm[player].affixer)
  2781.                 {   if (worm[player].position == -1)
  2782.                         worm[player].posidir = 1;
  2783.                     elif (worm[player].position == 1)
  2784.                         worm[player].posidir = -1;
  2785.                     worm[player].position += worm[player].posidir;
  2786.                     if (worm[player].deltax == 0)
  2787.                         protector[player][i].relx = worm[player].position;
  2788.                     elif (worm[player].deltay == 0)
  2789.                         protector[player][i].rely = worm[player].position;
  2790.                     elif (worm[player].position == -1)
  2791.                         protector[player][i].relx = worm[player].deltax * (DISTANCE_NOSE - 1);
  2792.                     elif (worm[player].position == 1)
  2793.                         protector[player][i].rely = worm[player].deltay * (DISTANCE_NOSE - 1);
  2794.             }   }
  2795.             elif (!worm[player].affixer)
  2796.             {   if (protector[player][i].relx == 1 && protector[player][i].rely == -1)
  2797.                 {   protector[player][i].deltax = 0;
  2798.                     protector[player][i].deltay = 1;
  2799.                 } elif (protector[player][i].relx == 1 && protector[player][i].rely == 1)
  2800.                 {   protector[player][i].deltax = -1;
  2801.                     protector[player][i].deltay = 0;
  2802.                 } elif (protector[player][i].relx == -1 && protector[player][i].rely == 1)
  2803.                 {   protector[player][i].deltax = 0;
  2804.                     protector[player][i].deltay = -1;
  2805.                 } elif (protector[player][i].relx == -1 && protector[player][i].rely == -1)
  2806.                 {   protector[player][i].deltax = 1;
  2807.                     protector[player][i].deltay = 0;
  2808.                 }
  2809.                 protector[player][i].relx += protector[player][i].deltax;
  2810.                 protector[player][i].rely += protector[player][i].deltay;
  2811.             }
  2812.             protector[player][i].x = worm[player].x + protector[player][i].relx;
  2813.             protector[player][i].y = worm[player].y + protector[player][i].rely;
  2814.             if (!valid(protector[player][i].x, protector[player][i].y))
  2815.             {   protector[player][i].visible = FALSE;
  2816. }   }   }   }
  2817.  
  2818. MODULE void protectorloop2(SBYTE player)
  2819. {   SBYTE thisprot;
  2820.  
  2821.     // protector collision detection
  2822.     for (thisprot = 0; thisprot <= PROTECTORS; thisprot++)
  2823.     {   if (protector[player][thisprot].alive && protector[player][thisprot].visible)
  2824.         {   protcol(player, protector[player][thisprot].x, protector[player][thisprot].y, thisprot);
  2825.  
  2826.             // we now need to recheck whether the protector should be visible or not
  2827.             // this might be defensive programming to hide a bug, or might be legitimate
  2828.             if (!valid(protector[player][thisprot].x, protector[player][thisprot].y))
  2829.             {   protector[player][thisprot].visible = FALSE;
  2830.             }
  2831.  
  2832.             // draw protector
  2833.             if (protector[player][thisprot].alive && protector[player][thisprot].visible) // in case protector has just been killed, etc.
  2834.             {   change(protector[player][thisprot].x, protector[player][thisprot].y, FIRSTPROTECTOR + player);
  2835. }   }   }   }
  2836.  
  2837. MODULE void turncreature(UBYTE which)
  2838. {    switch(creature[which].dir)
  2839.    {   case 0:
  2840.                                     creature[which].deltax = 0;
  2841.                                     creature[which].deltay = -1;
  2842.                                 break;
  2843.                                 case 1:
  2844.                                     creature[which].deltax = 1;
  2845.                                     creature[which].deltay = -1;
  2846.                                 break;
  2847.                                 case 2:
  2848.                                     creature[which].deltax = 1;
  2849.                                     creature[which].deltay = 0;
  2850.                                 break;
  2851.                                 case 3:
  2852.                                     creature[which].deltax = 1;
  2853.                                     creature[which].deltay = 1;
  2854.                                 break;
  2855.                                 case 4:
  2856.                                     creature[which].deltax = 0;
  2857.                                     creature[which].deltay = 1;
  2858.                                 break;
  2859.                                 case 5:
  2860.                                     creature[which].deltax = -1;
  2861.                                     creature[which].deltay = 1;
  2862.                                 break;
  2863.                                 case 6:
  2864.                                     creature[which].deltax = -1;
  2865.                                     creature[which].deltay = 0;
  2866.                                 break;
  2867.                                 case 7:
  2868.                                     creature[which].deltax = -1;
  2869.                                     creature[which].deltay = -1;
  2870.                                 break;
  2871.                                 default:
  2872.                                     assert(0);
  2873.                                     creature[which].deltax = creature[which].deltay = 0; // to avoid spurious warnings
  2874.                                 break;
  2875. }   }
  2876.